diff --git a/crypto/message.go b/crypto/message.go index d6072fe..4f34be4 100644 --- a/crypto/message.go +++ b/crypto/message.go @@ -92,7 +92,7 @@ func NewPlainMessageFromFile(data []byte, filename string, time uint32) *PlainMe // This allows seamless conversion to clear text signed messages (see RFC 4880 5.2.1 and 7.1). func NewPlainMessageFromString(text string) *PlainMessage { return &PlainMessage{ - Data: []byte(internal.CanonicalizeAndTrim(text)), + Data: []byte(internal.Canonicalize(text)), TextType: true, Filename: "", Time: uint32(GetUnixTime()), diff --git a/crypto/signature_collector.go b/crypto/signature_collector.go index b5aefa6..05f2ecb 100644 --- a/crypto/signature_collector.go +++ b/crypto/signature_collector.go @@ -99,7 +99,7 @@ func (sc *SignatureCollector) Accept( } sc.signature = string(buffer) str, _ := ioutil.ReadAll(rawBody) - canonicalizedBody := internal.CanonicalizeAndTrim(string(str)) + canonicalizedBody := internal.Canonicalize(internal.TrimEachLine(string(str))) rawBody = bytes.NewReader([]byte(canonicalizedBody)) if sc.keyring != nil { _, err = openpgp.CheckArmoredDetachedSignature(sc.keyring, rawBody, bytes.NewReader(buffer), sc.config) diff --git a/helper/cleartext.go b/helper/cleartext.go index c318739..d5517b1 100644 --- a/helper/cleartext.go +++ b/helper/cleartext.go @@ -2,6 +2,7 @@ package helper import ( "github.com/ProtonMail/gopenpgp/v2/crypto" + "github.com/ProtonMail/gopenpgp/v2/internal" "github.com/pkg/errors" ) @@ -48,7 +49,7 @@ func VerifyCleartextMessageArmored(publicKey, armored string, verifyTime int64) // SignCleartextMessage signs text given a private keyring, canonicalizes and // trims the newlines, and returns the PGP-compliant special armoring. func SignCleartextMessage(keyRing *crypto.KeyRing, text string) (string, error) { - message := crypto.NewPlainMessageFromString(text) + message := crypto.NewPlainMessageFromString(internal.TrimEachLine(text)) signature, err := keyRing.SignDetached(message) if err != nil { @@ -67,7 +68,7 @@ func VerifyCleartextMessage(keyRing *crypto.KeyRing, armored string, verifyTime return "", errors.Wrap(err, "gopengpp: unable to unarmor cleartext message") } - message := crypto.NewPlainMessageFromString(clearTextMessage.GetString()) + message := crypto.NewPlainMessageFromString(internal.TrimEachLine(clearTextMessage.GetString())) signature := crypto.NewPGPSignature(clearTextMessage.GetBinarySignature()) err = keyRing.VerifyDetached(message, signature, verifyTime) if err != nil { diff --git a/helper/cleartext_test.go b/helper/cleartext_test.go index 6cf25b6..1e39ff9 100644 --- a/helper/cleartext_test.go +++ b/helper/cleartext_test.go @@ -45,5 +45,5 @@ func TestSignClearText(t *testing.T) { if err != nil { t.Fatal("Cannot parse message:", err) } - assert.Exactly(t, internal.CanonicalizeAndTrim(inputPlainText), string(clearTextMessage.GetBinary())) + assert.Exactly(t, internal.Canonicalize(internal.TrimEachLine(inputPlainText)), string(clearTextMessage.GetBinary())) } diff --git a/internal/common.go b/internal/common.go index 9704cd0..534b33d 100644 --- a/internal/common.go +++ b/internal/common.go @@ -7,14 +7,18 @@ import ( "github.com/ProtonMail/gopenpgp/v2/constants" ) -func CanonicalizeAndTrim(text string) string { +func Canonicalize(text string) string { + return strings.ReplaceAll(strings.ReplaceAll(text, "\r\n", "\n"), "\n", "\r\n") +} + +func TrimEachLine(text string) string { lines := strings.Split(text, "\n") for i := range lines { lines[i] = strings.TrimRight(lines[i], " \t\r") } - return strings.Join(lines, "\r\n") + return strings.Join(lines, "\n") } // CreationTimeOffset stores the amount of seconds that a signature may be