From b42e382224bef7220cb57d23235762113c1a790d Mon Sep 17 00:00:00 2001 From: Aron Wussler Date: Tue, 14 May 2019 16:08:25 +0000 Subject: [PATCH] Add signature tests, fix tests --- crypto/base_test.go | 6 ++- crypto/key_test.go | 9 ++-- crypto/keyring.go | 5 +-- crypto/keyring_test.go | 9 ++-- crypto/message_test.go | 10 ++--- crypto/mime_test.go | 15 +++---- crypto/sign_detached.go | 2 +- crypto/signature_test.go | 92 ++++++++++++++++++++++++++++++++++++++++ 8 files changed, 121 insertions(+), 27 deletions(-) create mode 100644 crypto/signature_test.go diff --git a/crypto/base_test.go b/crypto/base_test.go index 5fb17fb..8b0601d 100644 --- a/crypto/base_test.go +++ b/crypto/base_test.go @@ -2,14 +2,18 @@ package crypto import ( "io/ioutil" + "strings" ) var err error -func readTestFile(name string) string { +func readTestFile(name string, trimNewlines bool) string { data, err := ioutil.ReadFile("testdata/" + name) if err != nil { panic(err) } + if trimNewlines { + return strings.TrimRight(string(data), "\n") + } return string(data) } diff --git a/crypto/key_test.go b/crypto/key_test.go index 8e608dc..cbc750c 100644 --- a/crypto/key_test.go +++ b/crypto/key_test.go @@ -124,9 +124,8 @@ func TestUpdatePrivateKeysPassphrase(t *testing.T) { passphrase = newPassphrase } -// ExampleCheckKey to track changes in test data -func ExampleCheckKey() { - _, _ = pmCrypto.CheckKey(readTestFile("keyring_publicKey")) +func ExampleCheckKeys() { + _, _ = pmCrypto.CheckKey(readTestFile("keyring_publicKey", false)) // Output: // SubKey:37e4bcf09b36e34012d10c0247dc67b5cb8267f6 // PrimaryKey:6e8ba229b0cccaf6962f97953eb6259edf21df24 @@ -148,8 +147,8 @@ func TestIsKeyExpired(t *testing.T) { pmCrypto.UpdateTime(1557754627) // 2019-05-13T13:37:07+00:00 - expRes, expErr := pmCrypto.IsKeyExpired(readTestFile("key_expiredKey")) - futureRes, futureErr := pmCrypto.IsKeyExpired(readTestFile("key_futureKey")) + expRes, expErr := pmCrypto.IsKeyExpired(readTestFile("key_expiredKey", false)) + futureRes, futureErr := pmCrypto.IsKeyExpired(readTestFile("key_futureKey", false)) assert.Exactly(t, true, expRes) assert.Exactly(t, true, futureRes) diff --git a/crypto/keyring.go b/crypto/keyring.go index ae35ac5..3b14c34 100644 --- a/crypto/keyring.go +++ b/crypto/keyring.go @@ -125,10 +125,9 @@ func (kr *KeyRing) GetSigningEntity(passphrase string) (*openpgp.Entity, error) if err := e.PrivateKey.Decrypt([]byte(passphrase)); err != nil { continue } - - signEntity = e - break } + signEntity = e + break } } if signEntity == nil { diff --git a/crypto/keyring_test.go b/crypto/keyring_test.go index de44b1b..3021f22 100644 --- a/crypto/keyring_test.go +++ b/crypto/keyring_test.go @@ -39,12 +39,13 @@ var ( func init() { var err error - testPrivateKeyRing, err = ReadArmoredKeyRing(strings.NewReader(readTestFile("keyring_privateKey"))) + + testPrivateKeyRing, err = ReadArmoredKeyRing(strings.NewReader(readTestFile("keyring_privateKey", false))) if err != nil { panic(err) } - testPublicKeyRing, err = ReadArmoredKeyRing(strings.NewReader(readTestFile("keyring_publicKey"))) + testPublicKeyRing, err = ReadArmoredKeyRing(strings.NewReader(readTestFile("keyring_publicKey", false))) if err != nil { panic(err) } @@ -56,7 +57,7 @@ func init() { } func TestKeyRing_Decrypt(t *testing.T) { - ss, err := testPrivateKeyRing.DecryptString(readTestFile("keyring_token")) + ss, err := testPrivateKeyRing.DecryptString(readTestFile("keyring_token", false)) if err != nil { t.Fatal("Cannot decrypt token:", err) } @@ -92,7 +93,7 @@ func TestKeyRing_ArmoredPublicKeyString(t *testing.T) { t.Fatal("Expected no error while decoding armored public key, got:", err) } - expected, err := armor.Decode(strings.NewReader(readTestFile("keyring_publicKey"))) + expected, err := armor.Decode(strings.NewReader(readTestFile("keyring_publicKey", false))) if err != nil { t.Fatal("Expected no error while decoding expected armored public key, got:", err) } diff --git a/crypto/message_test.go b/crypto/message_test.go index d6be61e..e97b561 100644 --- a/crypto/message_test.go +++ b/crypto/message_test.go @@ -17,10 +17,10 @@ func TestMessageEncryptionWithPassword(t *testing.T) { t.Fatal("Expected no error when encrypting, got:", err) } // Decrypt data with wrong password - text, err := pmCrypto.DecryptMessageWithPassword(armor, "wrong password") + _, err = pmCrypto.DecryptMessageWithPassword(armor, "wrong password") assert.NotNil(t, err) // Decrypt data with the good password - text, err = pmCrypto.DecryptMessageWithPassword(armor, password) + text, err := pmCrypto.DecryptMessageWithPassword(armor, password) if err != nil { t.Fatal("Expected no error when decrypting, got:", err) } @@ -33,9 +33,9 @@ func TestMessageEncryption(t *testing.T) { message = "plain text" ) - testPrivateKeyRing, err = ReadArmoredKeyRing(strings.NewReader(readTestFile("keyring_privateKey"))) - testPrivateKeyRing.Unlock([]byte(testMailboxPassword)) - testPublicKeyRing, err = ReadArmoredKeyRing(strings.NewReader(readTestFile("keyring_publicKey"))) + testPrivateKeyRing, err = ReadArmoredKeyRing(strings.NewReader(readTestFile("keyring_privateKey", false))) + _ = testPrivateKeyRing.Unlock([]byte(testMailboxPassword)) + testPublicKeyRing, _ = ReadArmoredKeyRing(strings.NewReader(readTestFile("keyring_publicKey", false))) armor, err := pmCrypto.EncryptMessage(message, testPublicKeyRing, testPrivateKeyRing, testMailboxPassword, false) if err != nil { diff --git a/crypto/mime_test.go b/crypto/mime_test.go index 4ba0519..2db577a 100644 --- a/crypto/mime_test.go +++ b/crypto/mime_test.go @@ -4,7 +4,6 @@ import ( "github.com/stretchr/testify/assert" "github.com/ProtonMail/go-pm-crypto/internal" "io/ioutil" - "strings" "testing" ) @@ -17,7 +16,7 @@ type Callbacks struct { } func (t *Callbacks) OnBody(body string, mimetype string) { - assert.Exactly(t.Testing, readTestFile("mime_decryptedBody"), body) + assert.Exactly(t.Testing, readTestFile("mime_decryptedBody", false), body) } func (t Callbacks) OnAttachment(headers string, data []byte) { @@ -40,14 +39,14 @@ func TestDecrypt(t *testing.T) { Testing: t, } - block, err := internal.Unarmor(readTestFile("mime_publicKey")) + block, err := internal.Unarmor(readTestFile("mime_publicKey", false)) if err != nil { t.Fatal("Cannot unarmor public key: ", err) } publicKeyUnarmored, _ := ioutil.ReadAll(block.Body) - block, err = internal.Unarmor(readTestFile("mime_privateKey")) + block, err = internal.Unarmor(readTestFile("mime_privateKey", false)) if err != nil { t.Fatal("Cannot unarmor private key: ", err) } @@ -55,7 +54,7 @@ func TestDecrypt(t *testing.T) { privateKeyUnarmored, _ := ioutil.ReadAll(block.Body) pmCrypto.DecryptMIMEMessage( - readTestFile("mime_pgpMessage"), + readTestFile("mime_pgpMessage", false), pmCrypto.BuildKeyRingNoError(publicKeyUnarmored), pmCrypto.BuildKeyRingNoError(privateKeyUnarmored), privateKeyPassword, @@ -64,7 +63,7 @@ func TestDecrypt(t *testing.T) { } func TestParse(t *testing.T) { - body, _, atts, attHeaders, err := pmCrypto.parseMIME(readTestFile("mime_testMessage"), nil) + body, _, atts, attHeaders, err := pmCrypto.parseMIME(readTestFile("mime_testMessage", false), nil) if err != nil { t.Error("Expected no error while parsing message, got:", err) @@ -74,7 +73,7 @@ func TestParse(t *testing.T) { _ = attHeaders bodyData, _ := body.GetBody() - assert.Exactly(t, strings.Trim(readTestFile("mime_decodedBody"), "\n"), bodyData) - assert.Exactly(t, readTestFile("mime_decodedBodyHeaders"), body.GetHeaders()) + assert.Exactly(t, readTestFile("mime_decodedBody", true), bodyData) + assert.Exactly(t, readTestFile("mime_decodedBodyHeaders", false), body.GetHeaders()) assert.Exactly(t, 2, len(atts)) } diff --git a/crypto/sign_detached.go b/crypto/sign_detached.go index 34f4d45..e809331 100644 --- a/crypto/sign_detached.go +++ b/crypto/sign_detached.go @@ -112,7 +112,7 @@ func verifySignature( } if signer == nil { - return false, errors.New("signer is empty") + return false, errors.New("pmcrypto: signer is empty") } // if signer.PrimaryKey.KeyId != signed.PrimaryKey.KeyId { // // t.Errorf("wrong signer got:%x want:%x", signer.PrimaryKey.KeyId, 0) diff --git a/crypto/signature_test.go b/crypto/signature_test.go new file mode 100644 index 0000000..cb96e68 --- /dev/null +++ b/crypto/signature_test.go @@ -0,0 +1,92 @@ +package crypto + +import ( + "strings" + "regexp" + "testing" + + "github.com/stretchr/testify/assert" +) + +const signedPlainText = "Signed message" +const testTime = 1557754627 // 2019-05-13T13:37:07+00:00 + +var signingKeyRing *KeyRing +var signature, signatureBin string + +func TestSignTextDetached(t *testing.T) { + signingKeyRing, err := ReadArmoredKeyRing(strings.NewReader(readTestFile("keyring_privateKey", false))) + if err != nil { + t.Fatal("Cannot read private key:", err) + } + + signature, err = pmCrypto.SignTextDetached(signedPlainText, signingKeyRing, "", true) + assert.EqualError(t, err, "pmcrypto: cannot sign message, unable to unlock signer key") + + // Password defined in keyring_test + signature, err = pmCrypto.SignTextDetached(signedPlainText, signingKeyRing, testMailboxPassword, true) + if err != nil { + t.Fatal("Cannot generate signature with encrypted key:", err) + } + + // Reset keyring to locked state + signingKeyRing, _ = ReadArmoredKeyRing(strings.NewReader(readTestFile("keyring_privateKey", false))) + // Password defined in keyring_test + err = signingKeyRing.Unlock([]byte(testMailboxPassword)) + if err != nil { + t.Fatal("Cannot decrypt private key:", err) + } + + signatureDec, err := pmCrypto.SignTextDetached(signedPlainText, signingKeyRing, "", true) + if err != nil { + t.Fatal("Cannot generate signature with decrypted key:", err) + } + + rTest := regexp.MustCompile("(?s)^-----BEGIN PGP SIGNATURE-----.*-----END PGP SIGNATURE-----$") + assert.Regexp(t, rTest, signature) + assert.Exactly(t, signatureDec, signature) +} + +func TestSignBinDetached(t *testing.T) { + var err error + + // Reset keyring to locked state + signingKeyRing, _ = ReadArmoredKeyRing(strings.NewReader(readTestFile("keyring_privateKey", false))) + signatureBin, err = pmCrypto.SignBinDetached([]byte(signedPlainText), signingKeyRing, "") + assert.EqualError(t, err, "pmcrypto: cannot sign message, unable to unlock signer key") + + // Password defined in keyring_test + signatureBin, err = pmCrypto.SignBinDetached([]byte(signedPlainText), signingKeyRing, testMailboxPassword) + if err != nil { + t.Fatal("Cannot generate signature with encrypted key:", err) + } + + rTest := regexp.MustCompile("(?s)^-----BEGIN PGP SIGNATURE-----.*-----END PGP SIGNATURE-----$") + assert.Regexp(t, rTest, signatureBin) +} + +func TestVerifyTextDetachedSig(t *testing.T) { + verified, err := pmCrypto.VerifyTextDetachedSig(signature, signedPlainText, signingKeyRing, testTime) + if err != nil { + t.Fatal("Cannot verify plaintext signature:", err) + } + + assert.Exactly(t, true, verified) +} + +func TestVerifyTextDetachedSigWrong(t *testing.T) { + verified, err := pmCrypto.VerifyTextDetachedSig(signature, "wrong text", signingKeyRing, testTime) + + assert.EqualError(t, err, "pmcrypto: signer is empty") + assert.Exactly(t, false, verified) +} + + +func TestVerifyBinDetachedSig(t *testing.T) { + verified, err := pmCrypto.VerifyBinDetachedSig(signatureBin, []byte(signedPlainText), signingKeyRing, testTime) + if err != nil { + t.Fatal("Cannot verify binary signature:", err) + } + + assert.Exactly(t, true, verified) +}