diff --git a/README.md b/README.md index 7542052..623ffb8 100644 --- a/README.md +++ b/README.md @@ -148,11 +148,17 @@ const privkey = `-----BEGIN PGP PRIVATE KEY BLOCK----- const passphrase = []byte(`the passphrase of the private key`) // Passphrase of the privKey -// encrypt message using public key +// encrypt plain text message using public key armor, err := helper.EncryptMessageArmored(pubkey, "plain text") -// decrypt armored encrypted message using the private key +// encrypt binary message using public key +armor, err := helper.EncryptBinaryMessageArmored(pubkey, []byte("plain text")) + +// decrypt armored encrypted message using the private key and got plain text decrypted, err := helper.DecryptMessageArmored(privkey, passphrase, armor) + +// decrypt armored encrypted message using the private key and got binary +decrypted, err := helper.DecryptBinaryMessageArmored(privkey, passphrase, armor) ``` With signatures: diff --git a/helper/helper.go b/helper/helper.go index 9cf6a8c..eba0f3f 100644 --- a/helper/helper.go +++ b/helper/helper.go @@ -43,30 +43,8 @@ func DecryptMessageWithPassword(password []byte, ciphertext string) (plaintext s // EncryptMessageArmored generates an armored PGP message given a plaintext and // an armored public key. -func EncryptMessageArmored(key, plaintext string) (ciphertext string, err error) { - var publicKey *crypto.Key - var publicKeyRing *crypto.KeyRing - var pgpMessage *crypto.PGPMessage - - var message = crypto.NewPlainMessageFromString(plaintext) - - if publicKey, err = crypto.NewKeyFromArmored(key); err != nil { - return "", err - } - - if publicKeyRing, err = crypto.NewKeyRing(publicKey); err != nil { - return "", err - } - - if pgpMessage, err = publicKeyRing.Encrypt(message, nil); err != nil { - return "", err - } - - if ciphertext, err = pgpMessage.GetArmored(); err != nil { - return "", err - } - - return ciphertext, nil +func EncryptMessageArmored(key, plaintext string) (string, error) { + return encryptMessageArmored(key, crypto.NewPlainMessageFromString(plaintext)) } // EncryptSignMessageArmored generates an armored signed PGP message given a @@ -116,30 +94,10 @@ func EncryptSignMessageArmored( // and its passphrase. func DecryptMessageArmored( privateKey string, passphrase []byte, ciphertext string, -) (plaintext string, err error) { - var privateKeyObj, privateKeyUnlocked *crypto.Key - var privateKeyRing *crypto.KeyRing - var pgpMessage *crypto.PGPMessage - var message *crypto.PlainMessage +) (string, error) { + message, err := decryptMessageArmored(privateKey, passphrase, ciphertext) - if privateKeyObj, err = crypto.NewKeyFromArmored(privateKey); err != nil { - return "", err - } - - if privateKeyUnlocked, err = privateKeyObj.Unlock(passphrase); err != nil { - return "", err - } - defer privateKeyUnlocked.ClearPrivateParams() - - if privateKeyRing, err = crypto.NewKeyRing(privateKeyUnlocked); err != nil { - return "", err - } - - if pgpMessage, err = crypto.NewPGPMessageFromArmored(ciphertext); err != nil { - return "", err - } - - if message, err = privateKeyRing.Decrypt(pgpMessage, nil, 0); err != nil { + if err != nil { return "", err } @@ -240,3 +198,85 @@ func DecryptVerifyAttachment( return message.GetBinary(), nil } + +// EncryptBinaryMessageArmored generates an armored PGP message given a binary data and +// an armored public key. +func EncryptBinaryMessageArmored(key string, data []byte) (string, error) { + return encryptMessageArmored(key, crypto.NewPlainMessage(data)) +} + +// DecryptBinaryMessageArmored decrypts an armored PGP message given a private key +// and its passphrase. +func DecryptBinaryMessageArmored(privateKey string, passphrase []byte, ciphertext string) ([]byte, error) { + message, err := decryptMessageArmored(privateKey, passphrase, ciphertext) + + if err != nil { + return nil, err + } + + return message.GetBinary(), nil +} + +func encryptMessageArmored(key string, message *crypto.PlainMessage) (string, error) { + publicKey, err := crypto.NewKeyFromArmored(key) + + if err != nil { + return "", err + } + + publicKeyRing, err := crypto.NewKeyRing(publicKey) + + if err != nil { + return "", err + } + + pgpMessage, err := publicKeyRing.Encrypt(message, nil) + + if err != nil { + return "", err + } + + ciphertext, err := pgpMessage.GetArmored() + + if err != nil { + return "", err + } + + return ciphertext, nil +} + +func decryptMessageArmored(privateKey string, passphrase []byte, ciphertext string) (*crypto.PlainMessage, error) { + privateKeyObj, err := crypto.NewKeyFromArmored(privateKey) + + if err != nil { + return nil, err + } + + privateKeyUnlocked, err := privateKeyObj.Unlock(passphrase) + + if err != nil { + return nil, err + } + + defer privateKeyUnlocked.ClearPrivateParams() + + privateKeyRing, err := crypto.NewKeyRing(privateKeyUnlocked) + + if err != nil { + return nil, err + } + + pgpMessage, err := crypto.NewPGPMessageFromArmored(ciphertext) + + if err != nil { + return nil, err + } + + message, err := privateKeyRing.Decrypt(pgpMessage, nil, 0) + + if err != nil { + return nil, err + } + + return message, nil +} diff --git a/helper/helper_test.go b/helper/helper_test.go index b79feee..b0c3cb7 100644 --- a/helper/helper_test.go +++ b/helper/helper_test.go @@ -130,3 +130,27 @@ func TestAttachmentEncryptionVerification(t *testing.T) { assert.Exactly(t, attachment, decrypted) } + +func TestArmoredBinaryMessageEncryption(t *testing.T) { + plainData := []byte("Secret message") + + armored, err := EncryptBinaryMessageArmored(readTestFile("keyring_publicKey", false), plainData) + + if err != nil { + t.Fatal("Expected no error when encrypting, got:", err) + } + + assert.Exactly(t, true, crypto.IsPGPMessage(armored)) + + decrypted, err := DecryptBinaryMessageArmored( + readTestFile("keyring_privateKey", false), + testMailboxPassword, // Password defined in base_test + armored, + ) + + if err != nil { + t.Fatal("Expected no error when decrypting, got:", err) + } + + assert.Exactly(t, plainData, decrypted) +}