Add binary message helpers (#61)
* Add EncryptBinaryMessageArmored helper function to generate an armored PGP message given binary data and an armored public key * Add DecryptBinaryMessageArmored helper function to decrypt armored PGP message into binary data * Streamline the code and fix naming pattern + tests
This commit is contained in:
parent
88da5d44b1
commit
3b2e53c586
3 changed files with 119 additions and 49 deletions
10
README.md
10
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
|
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")
|
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)
|
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:
|
With signatures:
|
||||||
|
|
|
||||||
134
helper/helper.go
134
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
|
// EncryptMessageArmored generates an armored PGP message given a plaintext and
|
||||||
// an armored public key.
|
// an armored public key.
|
||||||
func EncryptMessageArmored(key, plaintext string) (ciphertext string, err error) {
|
func EncryptMessageArmored(key, plaintext string) (string, error) {
|
||||||
var publicKey *crypto.Key
|
return encryptMessageArmored(key, crypto.NewPlainMessageFromString(plaintext))
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// EncryptSignMessageArmored generates an armored signed PGP message given a
|
// EncryptSignMessageArmored generates an armored signed PGP message given a
|
||||||
|
|
@ -116,30 +94,10 @@ func EncryptSignMessageArmored(
|
||||||
// and its passphrase.
|
// and its passphrase.
|
||||||
func DecryptMessageArmored(
|
func DecryptMessageArmored(
|
||||||
privateKey string, passphrase []byte, ciphertext string,
|
privateKey string, passphrase []byte, ciphertext string,
|
||||||
) (plaintext string, err error) {
|
) (string, error) {
|
||||||
var privateKeyObj, privateKeyUnlocked *crypto.Key
|
message, err := decryptMessageArmored(privateKey, passphrase, ciphertext)
|
||||||
var privateKeyRing *crypto.KeyRing
|
|
||||||
var pgpMessage *crypto.PGPMessage
|
|
||||||
var message *crypto.PlainMessage
|
|
||||||
|
|
||||||
if privateKeyObj, err = crypto.NewKeyFromArmored(privateKey); err != nil {
|
if 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 {
|
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -240,3 +198,85 @@ func DecryptVerifyAttachment(
|
||||||
|
|
||||||
return message.GetBinary(), nil
|
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
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -130,3 +130,27 @@ func TestAttachmentEncryptionVerification(t *testing.T) {
|
||||||
|
|
||||||
assert.Exactly(t, attachment, decrypted)
|
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)
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue