diff --git a/ProposalChanges.md b/ProposalChanges.md index d8df1c5..82f9259 100644 --- a/ProposalChanges.md +++ b/ProposalChanges.md @@ -189,14 +189,14 @@ SetKey(kr *KeyRing, symKey *SymmetricKey) (packets string, err error): Renamed. ``` (pm *PmCrypto) IsKeyExpiredBin(publicKey []byte) (bool, error): -* (pgp *GopenPGP) IsKeyExpired(publicKey []byte) (bool, error) +* IsKeyExpired(publicKey []byte) (bool, error) ``` ### IsKeyExpired Renamed. ``` (pm *PmCrypto) IsKeyExpired(publicKey string) (bool, error): -* (pgp *GopenPGP) IsArmoredKeyExpired(publicKey string) (bool, error) +* IsArmoredKeyExpired(publicKey string) (bool, error) ``` ### GenerateRSAKeyWithPrimes @@ -205,7 +205,7 @@ Added `name` parameter. To emulate the old behaviour `name = email = userName + "@" + domain`. ``` (pm *PmCrypto) GenerateRSAKeyWithPrimes(userName, domain, passphrase, keyType string, bits int, prime1, prime2, prime3, prime4 []byte) (string, error): -* (pgp *GopenPGP) GenerateRSAKeyWithPrimes(name, email, passphrase, keyType string, bits int, prime1, prime2, prime3, prime4 []byte) (string, error): +* GenerateRSAKeyWithPrimes(name, email, passphrase, keyType string, bits int, prime1, prime2, prime3, prime4 []byte) (string, error): ``` ### GenerateKey @@ -214,7 +214,7 @@ Added `name` parameter. To emulate the old behaviour `name = email = userName + "@" + domain`. ``` (pm *PmCrypto) GenerateKey(userName, domain, passphrase, keyType string, bits int) (string, error) : -* (pgp *GopenPGP) GenerateKey(name, email, passphrase, keyType string, bits int) (string, error): +* GenerateKey(name, email, passphrase, keyType string, bits int) (string, error): ``` ### UpdatePrivateKeyPassphrase @@ -224,7 +224,7 @@ No change. Renamed. ``` (pm *PmCrypto) CheckKey(pubKey string) (string, error): -* (pgp *GopenPGP) PrintFingerprints(pubKey string) (string, error) +* PrintFingerprints(pubKey string) (string, error) ``` ## keyring.go @@ -277,7 +277,7 @@ Same as Encrypt*. If signature verification fails it will return a SignatureVeri Replaced with `IsPGPMessage` + `Decrypt*`. ``` (kr *KeyRing) DecryptStringIfNeeded(data string) (decrypted string, err error): -* (pgp *GopenPGP) IsPGPMessage(data string) bool +* IsPGPMessage(data string) bool ``` ### SignString, DetachedSign @@ -395,7 +395,7 @@ No change. Renamed. ``` (pm *PmCrypto) RandomTokenWith(size int) ([]byte, error): -* (pgp *GopenPGP) RandomTokenSize(size int) ([]byte, error) +* RandomTokenSize(size int) ([]byte, error) ``` ### GetSessionFromKeyPacket diff --git a/README.md b/README.md index ebbccf4..9fa6aaa 100644 --- a/README.md +++ b/README.md @@ -164,15 +164,15 @@ With binary data or advanced modes: // Keys initialization as before (omitted) var binMessage = NewPlainMessage(data) -publicKeyRing, err := pgp.BuildKeyRingArmored(publicKey) -privateKeyRing, err := pgp.BuildKeyRingArmored(privateKey) +publicKeyRing, err := crypto.BuildKeyRingArmored(publicKey) +privateKeyRing, err := crypto.BuildKeyRingArmored(privateKey) err = privateKeyRing.UnlockWithPassphrase(passphrase) pgpMessage, err := publicKeyRing.Encrypt(binMessage, privateKeyRing) // Armored message in pgpMessage.GetArmored() // pgpMessage can be obtained from NewPGPMessageFromArmored(ciphertext) -message, err := privateKeyRing.Decrypt(pgpMessage, publicKeyRing, pgp.GetUnixTime()) +message, err := privateKeyRing.Decrypt(pgpMessage, publicKeyRing, crypto.GetUnixTime()) // Original data in message.GetString() // `err` can be a SignatureVerificationError @@ -183,8 +183,6 @@ Keys are generated with the `GenerateKey` function, that returns the armored key The library supports RSA with different key lengths or Curve25519 keys. ```go -var pgp = crypto.GetGopenPGP() - const ( localPart = "name.surname" domain = "example.com" @@ -194,10 +192,10 @@ const ( ) // RSA -rsaKey, err := pgp.GenerateKey(localPart, domain, passphrase, "rsa", rsaBits) +rsaKey, err := crypto.GenerateKey(localPart, domain, passphrase, "rsa", rsaBits) // Curve25519 -ecKey, err := pgp.GenerateKey(localPart, domain, passphrase, "x25519", ecBits) +ecKey, err := crypto.GenerateKey(localPart, domain, passphrase, "x25519", ecBits) ``` ### Detached signatures for plain text messages @@ -214,7 +212,7 @@ const trimNewlines = false var message = NewPlaintextMessage("Verified message") -signingKeyRing, err := pgp.BuildKeyRingArmored(privkey) +signingKeyRing, err := crypto.BuildKeyRingArmored(privkey) signingKeyRing.UnlockWithPassphrase(passphrase) // if private key is locked with passphrase pgpSignature, err := signingKeyRing.SignDetached(message, trimNewlines) @@ -226,8 +224,6 @@ pgpSignature, err := signingKeyRing.SignDetached(message, trimNewlines) To verify a signature either private or public keyring can be provided. ```go -var pgp = crypto.GetGopenPGP() - const pubkey = `-----BEGIN PGP PUBLIC KEY BLOCK----- ... -----END PGP PUBLIC KEY BLOCK-----` @@ -238,9 +234,9 @@ const signature = `-----BEGIN PGP SIGNATURE----- message := NewPlaintextMessage("Verified message") pgpSignature, err := NewPGPSignatureFromArmored(signature) -signingKeyRing, err := pgp.BuildKeyRingArmored(pubkey) +signingKeyRing, err := crypto.BuildKeyRingArmored(pubkey) -err := signingKeyRing.VerifyDetached(message, pgpSignature, pgp.GetUnixTime()) +err := signingKeyRing.VerifyDetached(message, pgpSignature, crypto.GetUnixTime()) if err == nil { // verification success @@ -250,8 +246,6 @@ if err == nil { ### Detached signatures for binary data ```go -var pgp = crypto.GetGopenPGP() - const privkey = `-----BEGIN PGP PRIVATE KEY BLOCK----- ... -----END PGP PRIVATE KEY BLOCK-----` // encrypted private key @@ -259,7 +253,7 @@ const passphrase = "LongSecret" var message = NewPlainMessage(data) -signingKeyRing, err := pgp.BuildKeyRingArmored(privkey) +signingKeyRing, err := crypto.BuildKeyRingArmored(privkey) signingKeyRing.UnlockWithPassphrase(passphrase) // if private key is locked with passphrase pgpSignature, err := signingKeyRing.SignDetached(message) @@ -271,8 +265,6 @@ pgpSignature, err := signingKeyRing.SignDetached(message) To verify a signature either private or public keyring can be provided. ```go -var pgp = crypto.GetGopenPGP() - const pubkey = `-----BEGIN PGP PUBLIC KEY BLOCK----- ... -----END PGP PUBLIC KEY BLOCK-----` @@ -283,9 +275,9 @@ const signature = `-----BEGIN PGP SIGNATURE----- message := NewPlainMessage("Verified message") pgpSignature, err := NewPGPSignatureFromArmored(signature) -signingKeyRing, err := pgp.BuildKeyRingArmored(pubkey) +signingKeyRing, err := crypto.BuildKeyRingArmored(pubkey) -err := signingKeyRing.VerifyDetached(message, pgpSignature, pgp.GetUnixTime()) +err := signingKeyRing.VerifyDetached(message, pgpSignature, crypto.GetUnixTime()) if err == nil { // verification success @@ -304,8 +296,7 @@ If verification fails an error will be returned. ```go // Keys initialization as before (omitted) -var pgp = crypto.GetGopenPGP() -var verifyTime = pgp.GetUnixTime() +var verifyTime = crypto.GetUnixTime() verifiedPlainText, err := VerifyCleartextMessageArmored(publicKey, armored, verifyTime) ``` diff --git a/crypto/attachment.go b/crypto/attachment.go index e37b185..cdf232c 100644 --- a/crypto/attachment.go +++ b/crypto/attachment.go @@ -59,7 +59,7 @@ func (keyRing *KeyRing) newAttachmentProcessor( config := &packet.Config{ DefaultCipher: packet.CipherAES256, - Time: pgp.getTimeGenerator(), + Time: getTimeGenerator(), } reader, writer := io.Pipe() @@ -124,7 +124,7 @@ func (keyRing *KeyRing) DecryptAttachment(message *PGPSplitMessage) (*PlainMessa encryptedReader := io.MultiReader(keyReader, dataReader) - config := &packet.Config{Time: pgp.getTimeGenerator()} + config := &packet.Config{Time: getTimeGenerator()} md, err := openpgp.ReadMessage(encryptedReader, privKeyEntries, nil, config) if err != nil { diff --git a/crypto/gopenpgp.go b/crypto/gopenpgp.go index 9b7fd84..dc51495 100644 --- a/crypto/gopenpgp.go +++ b/crypto/gopenpgp.go @@ -9,3 +9,5 @@ type GopenPGP struct { latestServerTime int64 latestClientTime time.Time } + +var pgp = GopenPGP{} diff --git a/crypto/key.go b/crypto/key.go index 23ea8f4..10b8309 100644 --- a/crypto/key.go +++ b/crypto/key.go @@ -17,8 +17,8 @@ import ( ) // IsKeyExpired checks whether the given (unarmored, binary) key is expired. -func (pgp *GopenPGP) IsKeyExpired(publicKey []byte) (bool, error) { - now := pgp.getNow() +func IsKeyExpired(publicKey []byte) (bool, error) { + now := getNow() pubKeyReader := bytes.NewReader(publicKey) pubKeyEntries, err := openpgp.ReadKeyRing(pubKeyReader) if err != nil { @@ -33,15 +33,15 @@ func (pgp *GopenPGP) IsKeyExpired(publicKey []byte) (bool, error) { } // IsArmoredKeyExpired checks whether the given armored key is expired. -func (pgp *GopenPGP) IsArmoredKeyExpired(publicKey string) (bool, error) { +func IsArmoredKeyExpired(publicKey string) (bool, error) { rawPubKey, err := armor.Unarmor(publicKey) if err != nil { return false, err } - return pgp.IsKeyExpired(rawPubKey) + return IsKeyExpired(rawPubKey) } -func (pgp *GopenPGP) generateKey( +func generateKey( name, email, passphrase, keyType string, bits int, prime1, prime2, prime3, prime4 []byte, @@ -59,7 +59,7 @@ func (pgp *GopenPGP) generateKey( cfg := &packet.Config{ Algorithm: packet.PubKeyAlgoRSA, RSABits: bits, - Time: pgp.getTimeGenerator(), + Time: getTimeGenerator(), DefaultHash: crypto.SHA256, DefaultCipher: packet.CipherAES256, } @@ -115,24 +115,24 @@ func (pgp *GopenPGP) generateKey( } // GenerateRSAKeyWithPrimes generates a RSA key using the given primes. -func (pgp *GopenPGP) GenerateRSAKeyWithPrimes( +func GenerateRSAKeyWithPrimes( name, email, passphrase string, bits int, primeone, primetwo, primethree, primefour []byte, ) (string, error) { - return pgp.generateKey(name, email, passphrase, "rsa", bits, primeone, primetwo, primethree, primefour) + return generateKey(name, email, passphrase, "rsa", bits, primeone, primetwo, primethree, primefour) } // GenerateKey generates a key of the given keyType ("rsa" or "x25519"). // If keyType is "rsa", bits is the RSA bitsize of the key. // If keyType is "x25519" bits is unused. -func (pgp *GopenPGP) GenerateKey(name, email, passphrase, keyType string, bits int) (string, error) { - return pgp.generateKey(name, email, passphrase, keyType, bits, nil, nil, nil, nil) +func GenerateKey(name, email, passphrase, keyType string, bits int) (string, error) { + return generateKey(name, email, passphrase, keyType, bits, nil, nil, nil, nil) } // UpdatePrivateKeyPassphrase decrypts the given armored privateKey with oldPassphrase, // re-encrypts it with newPassphrase, and returns the new armored key. -func (pgp *GopenPGP) UpdatePrivateKeyPassphrase( +func UpdatePrivateKeyPassphrase( privateKey string, oldPassphrase string, newPassphrase string, ) (string, error) { privKey := strings.NewReader(privateKey) @@ -178,7 +178,7 @@ func (pgp *GopenPGP) UpdatePrivateKeyPassphrase( } // PrintFingerprints is a debug helper function that prints the key and subkey fingerprints. -func (pgp *GopenPGP) PrintFingerprints(pubKey string) (string, error) { +func PrintFingerprints(pubKey string) (string, error) { pubKeyReader := strings.NewReader(pubKey) entries, err := openpgp.ReadArmoredKeyRing(pubKeyReader) if err != nil { diff --git a/crypto/key_test.go b/crypto/key_test.go index 59bb44c..a44ead4 100644 --- a/crypto/key_test.go +++ b/crypto/key_test.go @@ -25,12 +25,12 @@ var ( ) func TestGenerateKeys(t *testing.T) { - rsaKey, err = pgp.GenerateKey(name, domain, passphrase, "rsa", 1024) + rsaKey, err = GenerateKey(name, domain, passphrase, "rsa", 1024) if err != nil { t.Fatal("Cannot generate RSA key:", err) } - ecKey, err = pgp.GenerateKey(name, domain, passphrase, "x25519", 256) + ecKey, err = GenerateKey(name, domain, passphrase, "x25519", 256) if err != nil { t.Fatal("Cannot generate EC key:", err) } @@ -84,12 +84,12 @@ func TestGenerateKeyRings(t *testing.T) { func TestUpdatePrivateKeysPassphrase(t *testing.T) { newPassphrase := "I like GNU" - rsaKey, err = pgp.UpdatePrivateKeyPassphrase(rsaKey, passphrase, newPassphrase) + rsaKey, err = UpdatePrivateKeyPassphrase(rsaKey, passphrase, newPassphrase) if err != nil { t.Fatal("Error in changing RSA key's passphrase:", err) } - ecKey, err = pgp.UpdatePrivateKeyPassphrase(ecKey, passphrase, newPassphrase) + ecKey, err = UpdatePrivateKeyPassphrase(ecKey, passphrase, newPassphrase) if err != nil { t.Fatal("Error in changing EC key's passphrase:", err) } @@ -98,19 +98,19 @@ func TestUpdatePrivateKeysPassphrase(t *testing.T) { } func ExamplePrintFingerprints() { - _, _ = pgp.PrintFingerprints(readTestFile("keyring_publicKey", false)) + _, _ = PrintFingerprints(readTestFile("keyring_publicKey", false)) // Output: // SubKey:37e4bcf09b36e34012d10c0247dc67b5cb8267f6 // PrimaryKey:6e8ba229b0cccaf6962f97953eb6259edf21df24 } func TestIsArmoredKeyExpired(t *testing.T) { - rsaRes, err := pgp.IsArmoredKeyExpired(rsaPublicKey) + rsaRes, err := IsArmoredKeyExpired(rsaPublicKey) if err != nil { t.Fatal("Error in checking expiration of RSA key:", err) } - ecRes, err := pgp.IsArmoredKeyExpired(ecPublicKey) + ecRes, err := IsArmoredKeyExpired(ecPublicKey) if err != nil { t.Fatal("Error in checking expiration of EC key:", err) } @@ -118,10 +118,10 @@ func TestIsArmoredKeyExpired(t *testing.T) { assert.Exactly(t, false, rsaRes) assert.Exactly(t, false, ecRes) - pgp.UpdateTime(1557754627) // 2019-05-13T13:37:07+00:00 + UpdateTime(1557754627) // 2019-05-13T13:37:07+00:00 - expRes, expErr := pgp.IsArmoredKeyExpired(readTestFile("key_expiredKey", false)) - futureRes, futureErr := pgp.IsArmoredKeyExpired(readTestFile("key_futureKey", false)) + expRes, expErr := IsArmoredKeyExpired(readTestFile("key_expiredKey", false)) + futureRes, futureErr := IsArmoredKeyExpired(readTestFile("key_futureKey", false)) assert.Exactly(t, true, expRes) assert.Exactly(t, true, futureRes) @@ -139,7 +139,7 @@ func TestGenerateKeyWithPrimes(t *testing.T) { prime4, _ := base64.StdEncoding.DecodeString( "58UEDXTX29Q9JqvuE3Tn+Qj275CXBnJbA8IVM4d05cPYAZ6H43bPN01pbJqJTJw/cuFxs+8C+HNw3/MGQOExqw==") - staticRsaKey, err := pgp.GenerateRSAKeyWithPrimes(name, domain, passphrase, 1024, prime1, prime2, prime3, prime4) + staticRsaKey, err := GenerateRSAKeyWithPrimes(name, domain, passphrase, 1024, prime1, prime2, prime3, prime4) if err != nil { t.Fatal("Cannot generate RSA key:", err) } diff --git a/crypto/keyring.go b/crypto/keyring.go index 641ec89..5ab8faf 100644 --- a/crypto/keyring.go +++ b/crypto/keyring.go @@ -243,7 +243,7 @@ func (keyRing *KeyRing) ReadFrom(r io.Reader, armored bool) error { } // BuildKeyRing reads keyring from binary data -func (pgp *GopenPGP) BuildKeyRing(binKeys []byte) (keyRing *KeyRing, err error) { +func BuildKeyRing(binKeys []byte) (keyRing *KeyRing, err error) { keyRing = &KeyRing{} entriesReader := bytes.NewReader(binKeys) err = keyRing.ReadFrom(entriesReader, false) @@ -252,13 +252,13 @@ func (pgp *GopenPGP) BuildKeyRing(binKeys []byte) (keyRing *KeyRing, err error) } // BuildKeyRingNoError does not return error on fail -func (pgp *GopenPGP) BuildKeyRingNoError(binKeys []byte) (keyRing *KeyRing) { - keyRing, _ = pgp.BuildKeyRing(binKeys) +func BuildKeyRingNoError(binKeys []byte) (keyRing *KeyRing) { + keyRing, _ = BuildKeyRing(binKeys) return } // BuildKeyRingArmored reads armored string and returns keyring -func (pgp *GopenPGP) BuildKeyRingArmored(key string) (keyRing *KeyRing, err error) { +func BuildKeyRingArmored(key string) (keyRing *KeyRing, err error) { keyRaw, err := armorUtils.Unarmor(key) if err != nil { return nil, err diff --git a/crypto/keyring_message.go b/crypto/keyring_message.go index 23b82c8..4359d20 100644 --- a/crypto/keyring_message.go +++ b/crypto/keyring_message.go @@ -44,7 +44,7 @@ func (keyRing *KeyRing) SignDetached(message *PlainMessage) (*PGPSignature, erro return nil, err } - config := &packet.Config{DefaultHash: crypto.SHA512, Time: pgp.getTimeGenerator()} + config := &packet.Config{DefaultHash: crypto.SHA512, Time: getTimeGenerator()} var outBuf bytes.Buffer //sign bin if err := openpgp.DetachSign(&outBuf, signEntity, message.NewReader(), config); err != nil { @@ -84,7 +84,7 @@ func asymmetricEncrypt(data []byte, publicKey *KeyRing, privateKey *KeyRing, isB } } - config := &packet.Config{DefaultCipher: packet.CipherAES256, Time: pgp.getTimeGenerator()} + config := &packet.Config{DefaultCipher: packet.CipherAES256, Time: getTimeGenerator()} hints := &openpgp.FileHints{ IsBinary: isBinary, @@ -125,7 +125,7 @@ func asymmetricDecrypt( privKeyEntries = append(privKeyEntries, additionalEntries...) } - config := &packet.Config{Time: pgp.getTimeGenerator()} + config := &packet.Config{Time: getTimeGenerator()} messageDetails, err := openpgp.ReadMessage(encryptedIO, privKeyEntries, nil, config) if err != nil { diff --git a/crypto/keyring_test.go b/crypto/keyring_test.go index 51dc206..46a8093 100644 --- a/crypto/keyring_test.go +++ b/crypto/keyring_test.go @@ -43,12 +43,12 @@ var testIdentity = &Identity{ func init() { var err error - testPrivateKeyRing, err = pgp.BuildKeyRingArmored(readTestFile("keyring_privateKey", false)) + testPrivateKeyRing, err = BuildKeyRingArmored(readTestFile("keyring_privateKey", false)) if err != nil { panic(err) } - testPublicKeyRing, err = pgp.BuildKeyRingArmored(readTestFile("keyring_publicKey", false)) + testPublicKeyRing, err = BuildKeyRingArmored(readTestFile("keyring_publicKey", false)) if err != nil { panic(err) } @@ -92,7 +92,7 @@ func TestKeyRing_ArmoredPublicKeyString(t *testing.T) { } func TestCheckPassphrase(t *testing.T) { - encryptedKeyRing, _ := pgp.BuildKeyRingArmored(readTestFile("keyring_privateKey", false)) + encryptedKeyRing, _ := BuildKeyRingArmored(readTestFile("keyring_privateKey", false)) isCorrect := encryptedKeyRing.CheckPassphrase("Wrong password") assert.Exactly(t, false, isCorrect) @@ -107,7 +107,7 @@ func TestIdentities(t *testing.T) { } func TestFilterExpiredKeys(t *testing.T) { - expiredKey, _ := pgp.BuildKeyRingArmored(readTestFile("key_expiredKey", false)) + expiredKey, _ := BuildKeyRingArmored(readTestFile("key_expiredKey", false)) keys := []*KeyRing{testPrivateKeyRing, expiredKey} unexpired, err := FilterExpiredKeys(keys) @@ -125,7 +125,7 @@ func TestGetPublicKey(t *testing.T) { t.Fatal("Expected no error while obtaining public key, got:", err) } - publicKeyRing, err := pgp.BuildKeyRing(publicKey) + publicKeyRing, err := BuildKeyRing(publicKey) if err != nil { t.Fatal("Expected no error while creating public key ring, got:", err) } @@ -150,7 +150,7 @@ func TestKeyIds(t *testing.T) { } func TestMutlipleKeyRing(t *testing.T) { - testPublicKeyRing, _ = pgp.BuildKeyRingArmored(readTestFile("keyring_publicKey", false)) + testPublicKeyRing, _ = BuildKeyRingArmored(readTestFile("keyring_publicKey", false)) assert.Exactly(t, 1, len(testPublicKeyRing.entities)) ids := testPublicKeyRing.KeyIds() diff --git a/crypto/message.go b/crypto/message.go index 0a45410..8f4fe30 100644 --- a/crypto/message.go +++ b/crypto/message.go @@ -368,7 +368,7 @@ func (msg *ClearTextMessage) GetArmored() (string, error) { // ---- UTILS ----- // IsPGPMessage checks if data if has armored PGP message format. -func (pgp *GopenPGP) IsPGPMessage(data string) bool { +func IsPGPMessage(data string) bool { re := regexp.MustCompile("^-----BEGIN " + constants.PGPMessageHeader + "-----(?s:.+)-----END " + constants.PGPMessageHeader + "-----") return re.MatchString(data) diff --git a/crypto/message_test.go b/crypto/message_test.go index eb7719a..878ba35 100644 --- a/crypto/message_test.go +++ b/crypto/message_test.go @@ -55,8 +55,8 @@ func TestBinaryMessageEncryptionWithSymmetricKey(t *testing.T) { func TestTextMessageEncryption(t *testing.T) { var message = NewPlainMessageFromString("plain text") - testPublicKeyRing, _ = pgp.BuildKeyRingArmored(readTestFile("keyring_publicKey", false)) - testPrivateKeyRing, err = pgp.BuildKeyRingArmored(readTestFile("keyring_privateKey", false)) + testPublicKeyRing, _ = BuildKeyRingArmored(readTestFile("keyring_publicKey", false)) + testPrivateKeyRing, err = BuildKeyRingArmored(readTestFile("keyring_privateKey", false)) // Password defined in keyring_test err = testPrivateKeyRing.UnlockWithPassphrase(testMailboxPassword) @@ -69,7 +69,7 @@ func TestTextMessageEncryption(t *testing.T) { t.Fatal("Expected no error when encrypting, got:", err) } - decrypted, err := testPrivateKeyRing.Decrypt(ciphertext, testPublicKeyRing, pgp.GetUnixTime()) + decrypted, err := testPrivateKeyRing.Decrypt(ciphertext, testPublicKeyRing, GetUnixTime()) if err != nil { t.Fatal("Expected no error when decrypting, got:", err) } @@ -80,8 +80,8 @@ func TestBinaryMessageEncryption(t *testing.T) { binData, _ := base64.StdEncoding.DecodeString("ExXmnSiQ2QCey20YLH6qlLhkY3xnIBC1AwlIXwK/HvY=") var message = NewPlainMessage(binData) - testPublicKeyRing, _ = pgp.BuildKeyRingArmored(readTestFile("keyring_publicKey", false)) - testPrivateKeyRing, err = pgp.BuildKeyRingArmored(readTestFile("keyring_privateKey", false)) + testPublicKeyRing, _ = BuildKeyRingArmored(readTestFile("keyring_publicKey", false)) + testPrivateKeyRing, err = BuildKeyRingArmored(readTestFile("keyring_privateKey", false)) // Password defined in keyring_test err = testPrivateKeyRing.UnlockWithPassphrase(testMailboxPassword) @@ -94,7 +94,7 @@ func TestBinaryMessageEncryption(t *testing.T) { t.Fatal("Expected no error when encrypting, got:", err) } - decrypted, err := testPrivateKeyRing.Decrypt(ciphertext, testPublicKeyRing, pgp.GetUnixTime()) + decrypted, err := testPrivateKeyRing.Decrypt(ciphertext, testPublicKeyRing, GetUnixTime()) if err != nil { t.Fatal("Expected no error when decrypting, got:", err) } @@ -109,7 +109,7 @@ func TestBinaryMessageEncryption(t *testing.T) { } func TestIssue11(t *testing.T) { - myKeyring, err := pgp.BuildKeyRingArmored(readTestFile("issue11_privatekey", false)) + myKeyring, err := BuildKeyRingArmored(readTestFile("issue11_privatekey", false)) if err != nil { t.Fatal("Expected no error while bulding private keyring, got:", err) } @@ -119,7 +119,7 @@ func TestIssue11(t *testing.T) { t.Fatal("Expected no error while unlocking private keyring, got:", err) } - senderKeyring, err := pgp.BuildKeyRingArmored(readTestFile("issue11_publickey", false)) + senderKeyring, err := BuildKeyRingArmored(readTestFile("issue11_publickey", false)) if err != nil { t.Fatal("Expected no error while building public keyring, got:", err) } @@ -140,7 +140,7 @@ func TestIssue11(t *testing.T) { } func TestSignedMessageDecryption(t *testing.T) { - testPrivateKeyRing, err = pgp.BuildKeyRingArmored(readTestFile("keyring_privateKey", false)) + testPrivateKeyRing, err = BuildKeyRingArmored(readTestFile("keyring_privateKey", false)) // Password defined in keyring_test err = testPrivateKeyRing.UnlockWithPassphrase(testMailboxPassword) @@ -163,7 +163,7 @@ func TestSignedMessageDecryption(t *testing.T) { func TestMultipleKeyMessageEncryption(t *testing.T) { var message = NewPlainMessageFromString("plain text") - testPublicKeyRing, _ = pgp.BuildKeyRingArmored(readTestFile("keyring_publicKey", false)) + testPublicKeyRing, _ = BuildKeyRingArmored(readTestFile("keyring_publicKey", false)) err = testPublicKeyRing.ReadFrom(strings.NewReader(readTestFile("mime_publicKey", false)), true) if err != nil { t.Fatal("Expected no error adding second public key, got:", err) @@ -171,7 +171,7 @@ func TestMultipleKeyMessageEncryption(t *testing.T) { assert.Exactly(t, 2, len(testPublicKeyRing.entities)) - testPrivateKeyRing, err = pgp.BuildKeyRingArmored(readTestFile("keyring_privateKey", false)) + testPrivateKeyRing, err = BuildKeyRingArmored(readTestFile("keyring_privateKey", false)) // Password defined in keyring_test err = testPrivateKeyRing.UnlockWithPassphrase(testMailboxPassword) @@ -199,7 +199,7 @@ func TestMultipleKeyMessageEncryption(t *testing.T) { } assert.Exactly(t, 2, numKeyPackets) - decrypted, err := testPrivateKeyRing.Decrypt(ciphertext, testPublicKeyRing, pgp.GetUnixTime()) + decrypted, err := testPrivateKeyRing.Decrypt(ciphertext, testPublicKeyRing, GetUnixTime()) if err != nil { t.Fatal("Expected no error when decrypting, got:", err) } diff --git a/crypto/mime.go b/crypto/mime.go index 91521d9..fcdcdfd 100644 --- a/crypto/mime.go +++ b/crypto/mime.go @@ -33,7 +33,7 @@ func (keyRing *KeyRing) DecryptMIMEMessage( return } - body, attachments, attachmentHeaders, err := pgp.parseMIME(decryptedMessage.GetString(), verifyKey) + body, attachments, attachmentHeaders, err := parseMIME(decryptedMessage.GetString(), verifyKey) if err != nil { callbacks.OnError(err) return @@ -48,14 +48,14 @@ func (keyRing *KeyRing) DecryptMIMEMessage( // ----- INTERNAL FUNCTIONS ----- -func (pgp GopenPGP) parseMIME( +func parseMIME( mimeBody string, verifierKey *KeyRing, ) (*gomime.BodyCollector, []string, []string, error) { mm, err := mail.ReadMessage(strings.NewReader(mimeBody)) if err != nil { return nil, nil, nil, err } - config := &packet.Config{DefaultCipher: packet.CipherAES256, Time: pgp.getTimeGenerator()} + config := &packet.Config{DefaultCipher: packet.CipherAES256, Time: getTimeGenerator()} h := textproto.MIMEHeader(mm.Header) mmBodyData, err := ioutil.ReadAll(mm.Body) diff --git a/crypto/mime_test.go b/crypto/mime_test.go index 1a1800d..2b37efb 100644 --- a/crypto/mime_test.go +++ b/crypto/mime_test.go @@ -37,7 +37,7 @@ func TestDecrypt(t *testing.T) { callbacks := Callbacks{ Testing: t, } - privateKeyRing, _ := pgp.BuildKeyRingArmored(readTestFile("mime_privateKey", false)) + privateKeyRing, _ := BuildKeyRingArmored(readTestFile("mime_privateKey", false)) err = privateKeyRing.UnlockWithPassphrase(privateKeyPassword) if err != nil { @@ -53,11 +53,11 @@ func TestDecrypt(t *testing.T) { message, nil, &callbacks, - pgp.GetUnixTime()) + GetUnixTime()) } func TestParse(t *testing.T) { - body, atts, attHeaders, err := pgp.parseMIME(readTestFile("mime_testMessage", false), nil) + body, atts, attHeaders, err := parseMIME(readTestFile("mime_testMessage", false), nil) if err != nil { t.Error("Expected no error while parsing message, got:", err) diff --git a/crypto/session.go b/crypto/session.go index 54e3c41..840d98b 100644 --- a/crypto/session.go +++ b/crypto/session.go @@ -10,13 +10,13 @@ import ( ) // RandomToken generated a random token of the same size of the keysize of the default cipher. -func (pgp *GopenPGP) RandomToken() ([]byte, error) { +func RandomToken() ([]byte, error) { config := &packet.Config{DefaultCipher: packet.CipherAES256} - return pgp.RandomTokenSize(config.DefaultCipher.KeySize()) + return RandomTokenSize(config.DefaultCipher.KeySize()) } // RandomTokenSize generates a random token with the specified key size -func (pgp *GopenPGP) RandomTokenSize(size int) ([]byte, error) { +func RandomTokenSize(size int) ([]byte, error) { config := &packet.Config{DefaultCipher: packet.CipherAES256} symKey := make([]byte, size) if _, err := io.ReadFull(config.Random(), symKey); err != nil { @@ -69,7 +69,7 @@ func (keyRing *KeyRing) EncryptSessionKey(sessionSplit *SymmetricKey) ([]byte, e var pub *packet.PublicKey for _, e := range keyRing.GetEntities() { - if encryptionKey, ok := e.EncryptionKey(pgp.getNow()); ok { + if encryptionKey, ok := e.EncryptionKey(getNow()); ok { pub = encryptionKey.PublicKey break } diff --git a/crypto/session_test.go b/crypto/session_test.go index f4e48cd..5e646fd 100644 --- a/crypto/session_test.go +++ b/crypto/session_test.go @@ -12,12 +12,12 @@ var testRandomToken []byte func TestRandomToken(t *testing.T) { var err error - testRandomToken, err = pgp.RandomToken() + testRandomToken, err = RandomToken() if err != nil { t.Fatal("Expected no error while generating default length random token, got:", err) } - token40, err := pgp.RandomTokenSize(40) + token40, err := RandomTokenSize(40) if err != nil { t.Fatal("Expected no error while generating random token, got:", err) } diff --git a/crypto/symmetrickey.go b/crypto/symmetrickey.go index 27d32e1..8761626 100644 --- a/crypto/symmetrickey.go +++ b/crypto/symmetrickey.go @@ -167,7 +167,7 @@ func symmetricEncrypt(message []byte, sk *SymmetricKey) ([]byte, error) { var outBuf bytes.Buffer config := &packet.Config{ - Time: pgp.getTimeGenerator(), + Time: getTimeGenerator(), DefaultCipher: sk.GetCipherFunc(), } @@ -196,7 +196,7 @@ func symmetricDecrypt(encryptedIO io.Reader, sk *SymmetricKey) ([]byte, error) { } config := &packet.Config{ - Time: pgp.getTimeGenerator(), + Time: getTimeGenerator(), } md, err := openpgp.ReadMessage(encryptedIO, nil, prompt, config) if err != nil { diff --git a/crypto/time.go b/crypto/time.go index 5ce642d..1795395 100644 --- a/crypto/time.go +++ b/crypto/time.go @@ -2,47 +2,50 @@ package crypto import ( "time" + "errors" ) -var pgp = GopenPGP{} - -// GetGopenPGP return global GopenPGP -func GetGopenPGP() *GopenPGP { - return &pgp -} - // UpdateTime updates cached time -func (pgp *GopenPGP) UpdateTime(newTime int64) { +func UpdateTime(newTime int64) { pgp.latestServerTime = newTime pgp.latestClientTime = time.Now() } // GetUnixTime gets latest cached time -func (pgp *GopenPGP) GetUnixTime() int64 { - return pgp.getNow().Unix() +func GetUnixTime() int64 { + return getNow().Unix() } // GetTime gets latest cached time -func (pgp *GopenPGP) GetTime() time.Time { - return pgp.getNow() +func GetTime() time.Time { + return getNow() } // ----- INTERNAL FUNCTIONS ----- // getNow returns current time -func (pgp *GopenPGP) getNow() time.Time { - if pgp.latestServerTime > 0 && !pgp.latestClientTime.IsZero() { - // Until is monotonic, it uses a monotonic clock in this case instead of the wall clock - extrapolate := int64(time.Until(pgp.latestClientTime).Seconds()) - return time.Unix(pgp.latestServerTime+extrapolate, 0) +func getNow() time.Time { + extrapolate, err := getDiff() + + if err != nil { + return time.Now() } - return time.Now() + return time.Unix(pgp.latestServerTime + extrapolate, 0) +} + +func getDiff() (int64, error) { + if pgp.latestServerTime > 0 && !pgp.latestClientTime.IsZero() { + // Since is monotonic, it uses a monotonic clock in this case instead of the wall clock + return int64(time.Since(pgp.latestClientTime).Seconds()), nil + } + + return 0, errors.New("Latest server time not available") } // getTimeGenerator Returns a time generator function -func (pgp *GopenPGP) getTimeGenerator() func() time.Time { +func getTimeGenerator() func() time.Time { return func() time.Time { - return pgp.getNow() + return getNow() } } diff --git a/crypto/time_test.go b/crypto/time_test.go new file mode 100644 index 0000000..dc262b0 --- /dev/null +++ b/crypto/time_test.go @@ -0,0 +1,21 @@ +package crypto + +import ( + "testing" + "time" + + "github.com/stretchr/testify/assert" +) + +func TestTime(t *testing.T) { + UpdateTime(1571072494) + time.Sleep(1 * time.Second) + diff, err := getDiff() + + if err != nil { + t.Fatal("Expected no error when calculating time difference, got:", err) + } + assert.Exactly(t, int64(1), diff) + + UpdateTime(testTime) +} diff --git a/helper/cleartext.go b/helper/cleartext.go index a96c68a..a0e40f9 100644 --- a/helper/cleartext.go +++ b/helper/cleartext.go @@ -10,7 +10,7 @@ import ( // SignCleartextMessageArmored signs text given a private key and its passphrase, canonicalizes and trims the newlines, // and returns the PGP-compliant special armoring func SignCleartextMessageArmored(privateKey, passphrase, text string) (string, error) { - signingKeyRing, err := pgp.BuildKeyRingArmored(privateKey) + signingKeyRing, err := crypto.BuildKeyRingArmored(privateKey) if err != nil { return "", err } @@ -26,7 +26,7 @@ func SignCleartextMessageArmored(privateKey, passphrase, text string) (string, e // VerifyCleartextMessageArmored verifies PGP-compliant armored signed plain text given the public key // and returns the text or err if the verification fails func VerifyCleartextMessageArmored(publicKey, armored string, verifyTime int64) (string, error) { - verifyKeyRing, err := pgp.BuildKeyRingArmored(publicKey) + verifyKeyRing, err := crypto.BuildKeyRingArmored(publicKey) if err != nil { return "", err } diff --git a/helper/cleartext_test.go b/helper/cleartext_test.go index de04f93..5905661 100644 --- a/helper/cleartext_test.go +++ b/helper/cleartext_test.go @@ -5,6 +5,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/ProtonMail/gopenpgp/crypto" ) const signedPlainText = "Signed message\n" @@ -29,7 +30,7 @@ func TestSignClearText(t *testing.T) { verified, err := VerifyCleartextMessageArmored( readTestFile("keyring_publicKey", false), armored, - pgp.GetUnixTime(), + crypto.GetUnixTime(), ) if err != nil { t.Fatal("Cannot verify message:", err) diff --git a/helper/helper.go b/helper/helper.go index b4e69a9..6939ac5 100644 --- a/helper/helper.go +++ b/helper/helper.go @@ -7,8 +7,6 @@ import ( "github.com/ProtonMail/gopenpgp/crypto" ) -var pgp = crypto.GetGopenPGP() - // EncryptMessageWithToken encrypts a string with a passphrase using AES256 func EncryptMessageWithToken( passphrase, plaintext string, @@ -62,7 +60,7 @@ func EncryptMessageArmored(publicKey, plaintext string) (ciphertext string, err var message = crypto.NewPlainMessageFromString(plaintext) - if publicKeyRing, err = pgp.BuildKeyRingArmored(publicKey); err != nil { + if publicKeyRing, err = crypto.BuildKeyRingArmored(publicKey); err != nil { return "", err } @@ -87,11 +85,11 @@ func EncryptSignMessageArmored( var message = crypto.NewPlainMessageFromString(plaintext) - if publicKeyRing, err = pgp.BuildKeyRingArmored(publicKey); err != nil { + if publicKeyRing, err = crypto.BuildKeyRingArmored(publicKey); err != nil { return "", err } - if privateKeyRing, err = pgp.BuildKeyRingArmored(privateKey); err != nil { + if privateKeyRing, err = crypto.BuildKeyRingArmored(privateKey); err != nil { return "", err } @@ -118,7 +116,7 @@ func DecryptMessageArmored( var pgpMessage *crypto.PGPMessage var message *crypto.PlainMessage - if privateKeyRing, err = pgp.BuildKeyRingArmored(privateKey); err != nil { + if privateKeyRing, err = crypto.BuildKeyRingArmored(privateKey); err != nil { return "", err } @@ -147,11 +145,11 @@ func DecryptVerifyMessageArmored( var pgpMessage *crypto.PGPMessage var message *crypto.PlainMessage - if publicKeyRing, err = pgp.BuildKeyRingArmored(publicKey); err != nil { + if publicKeyRing, err = crypto.BuildKeyRingArmored(publicKey); err != nil { return "", err } - if privateKeyRing, err = pgp.BuildKeyRingArmored(privateKey); err != nil { + if privateKeyRing, err = crypto.BuildKeyRingArmored(privateKey); err != nil { return "", err } @@ -163,7 +161,7 @@ func DecryptVerifyMessageArmored( return "", err } - if message, err = privateKeyRing.Decrypt(pgpMessage, publicKeyRing, pgp.GetUnixTime()); err != nil { + if message, err = privateKeyRing.Decrypt(pgpMessage, publicKeyRing, crypto.GetUnixTime()); err != nil { return "", err } @@ -183,11 +181,11 @@ func EncryptSignAttachment( var binMessage = crypto.NewPlainMessage(plainData) - if publicKeyRing, err = pgp.BuildKeyRingArmored(publicKey); err != nil { + if publicKeyRing, err = crypto.BuildKeyRingArmored(publicKey); err != nil { return nil, nil, nil, err } - if privateKeyRing, err = pgp.BuildKeyRingArmored(privateKey); err != nil { + if privateKeyRing, err = crypto.BuildKeyRingArmored(privateKey); err != nil { return nil, nil, nil, err } @@ -220,11 +218,11 @@ func DecryptVerifyAttachment( var packets = crypto.NewPGPSplitMessage(keyPacket, dataPacket) - if publicKeyRing, err = pgp.BuildKeyRingArmored(publicKey); err != nil { + if publicKeyRing, err = crypto.BuildKeyRingArmored(publicKey); err != nil { return nil, err } - if privateKeyRing, err = pgp.BuildKeyRingArmored(privateKey); err != nil { + if privateKeyRing, err = crypto.BuildKeyRingArmored(privateKey); err != nil { return nil, err } @@ -240,7 +238,7 @@ func DecryptVerifyAttachment( return nil, err } - if publicKeyRing.VerifyDetached(message, detachedSignature, pgp.GetUnixTime()) != nil { + if publicKeyRing.VerifyDetached(message, detachedSignature, crypto.GetUnixTime()) != nil { return nil, errors.New("gopenpgp: unable to verify attachment") } diff --git a/helper/helper_test.go b/helper/helper_test.go index cd00ce2..c9141a4 100644 --- a/helper/helper_test.go +++ b/helper/helper_test.go @@ -35,7 +35,7 @@ func TestArmoredTextMessageEncryption(t *testing.T) { t.Fatal("Expected no error when encrypting, got:", err) } - assert.Exactly(t, true, pgp.IsPGPMessage(armored)) + assert.Exactly(t, true, crypto.IsPGPMessage(armored)) decrypted, err := DecryptMessageArmored( readTestFile("keyring_privateKey", false), @@ -62,7 +62,7 @@ func TestArmoredTextMessageEncryptionVerification(t *testing.T) { t.Fatal("Expected no error when encrypting, got:", err) } - assert.Exactly(t, true, pgp.IsPGPMessage(armored)) + assert.Exactly(t, true, crypto.IsPGPMessage(armored)) _, err = DecryptVerifyMessageArmored( readTestFile("mime_publicKey", false), // Wrong public key diff --git a/helper/ios_test.go b/helper/ios_test.go index 0916755..6ee7b11 100644 --- a/helper/ios_test.go +++ b/helper/ios_test.go @@ -9,8 +9,8 @@ import ( ) func TestIOSSignedMessageDecryption(t *testing.T) { - testPrivateKeyRing, _ := pgp.BuildKeyRingArmored(readTestFile("keyring_privateKey", false)) - testPublicKeyRing, _ := pgp.BuildKeyRingArmored(readTestFile("mime_publicKey", false)) + testPrivateKeyRing, _ := crypto.BuildKeyRingArmored(readTestFile("keyring_privateKey", false)) + testPublicKeyRing, _ := crypto.BuildKeyRingArmored(readTestFile("mime_publicKey", false)) // Password defined in base_test err := testPrivateKeyRing.UnlockWithPassphrase(testMailboxPassword) @@ -23,7 +23,7 @@ func TestIOSSignedMessageDecryption(t *testing.T) { t.Fatal("Expected no error when unarmoring, got:", err) } - decrypted, err := DecryptExplicitVerify(pgpMessage, testPrivateKeyRing, testPublicKeyRing, pgp.GetUnixTime()) + decrypted, err := DecryptExplicitVerify(pgpMessage, testPrivateKeyRing, testPublicKeyRing, crypto.GetUnixTime()) if err != nil { t.Fatal("Expected no error when decrypting, got:", err) } @@ -31,14 +31,14 @@ func TestIOSSignedMessageDecryption(t *testing.T) { assert.Exactly(t, constants.SIGNATURE_NO_VERIFIER, decrypted.SignatureVerificationError.Status) assert.Exactly(t, readTestFile("message_plaintext", true), decrypted.Message.GetString()) - testPublicKeyRing, _ = pgp.BuildKeyRingArmored(readTestFile("keyring_publicKey", false)) + testPublicKeyRing, _ = crypto.BuildKeyRingArmored(readTestFile("keyring_publicKey", false)) pgpMessage, err = testPublicKeyRing.Encrypt(decrypted.Message, testPrivateKeyRing) if err != nil { t.Fatal("Expected no error when encrypting, got:", err) } - decrypted, err = DecryptExplicitVerify(pgpMessage, testPrivateKeyRing, testPublicKeyRing, pgp.GetUnixTime()) + decrypted, err = DecryptExplicitVerify(pgpMessage, testPrivateKeyRing, testPublicKeyRing, crypto.GetUnixTime()) if err != nil { t.Fatal("Expected no error when decrypting, got:", err) } @@ -46,7 +46,7 @@ func TestIOSSignedMessageDecryption(t *testing.T) { assert.Nil(t, decrypted.SignatureVerificationError) assert.Exactly(t, readTestFile("message_plaintext", true), decrypted.Message.GetString()) - decrypted, err = DecryptExplicitVerify(pgpMessage, testPublicKeyRing, testPublicKeyRing, pgp.GetUnixTime()) + decrypted, err = DecryptExplicitVerify(pgpMessage, testPublicKeyRing, testPublicKeyRing, crypto.GetUnixTime()) assert.NotNil(t, err) assert.Nil(t, decrypted) }