2019-12-27 19:35:43 +01:00
|
|
|
// helper contains several functions with a simple interface to extend usability and compatibility with gomobile
|
2019-06-03 17:00:01 +02:00
|
|
|
package helper
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"errors"
|
|
|
|
|
|
2019-12-27 19:35:43 +01:00
|
|
|
"github.com/ProtonMail/gopenpgp/v2/crypto"
|
2019-06-03 17:00:01 +02:00
|
|
|
)
|
|
|
|
|
|
2019-12-27 19:35:43 +01:00
|
|
|
// EncryptMessageWithPassword encrypts a string with a passphrase using AES256
|
|
|
|
|
func EncryptMessageWithPassword(password []byte, plaintext string) (ciphertext string, err error) {
|
2019-06-03 17:00:01 +02:00
|
|
|
var pgpMessage *crypto.PGPMessage
|
|
|
|
|
|
|
|
|
|
var message = crypto.NewPlainMessageFromString(plaintext)
|
|
|
|
|
|
2019-12-27 19:35:43 +01:00
|
|
|
if pgpMessage, err = crypto.EncryptMessageWithPassword(message, password); err != nil {
|
2019-06-03 17:00:01 +02:00
|
|
|
return "", err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ciphertext, err = pgpMessage.GetArmored(); err != nil {
|
|
|
|
|
return "", err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ciphertext, nil
|
|
|
|
|
}
|
|
|
|
|
|
2019-12-27 19:35:43 +01:00
|
|
|
// DecryptMessageWithPassword decrypts an armored message with a random token.
|
2019-06-03 17:00:01 +02:00
|
|
|
// The algorithm is derived from the armoring.
|
2019-12-27 19:35:43 +01:00
|
|
|
func DecryptMessageWithPassword(password []byte, ciphertext string) (plaintext string, err error) {
|
2019-06-03 17:00:01 +02:00
|
|
|
var message *crypto.PlainMessage
|
|
|
|
|
var pgpMessage *crypto.PGPMessage
|
|
|
|
|
|
|
|
|
|
if pgpMessage, err = crypto.NewPGPMessageFromArmored(ciphertext); err != nil {
|
|
|
|
|
return "", err
|
|
|
|
|
}
|
|
|
|
|
|
2019-12-27 19:35:43 +01:00
|
|
|
if message, err = crypto.DecryptMessageWithPassword(pgpMessage, password); err != nil {
|
2019-06-03 17:00:01 +02:00
|
|
|
return "", err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return message.GetString(), nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// EncryptMessageArmored generates an armored PGP message given a plaintext and an armored public key
|
2019-12-27 19:35:43 +01:00
|
|
|
func EncryptMessageArmored(key, plaintext string) (ciphertext string, err error) {
|
|
|
|
|
var publicKey *crypto.Key
|
2019-06-03 17:00:01 +02:00
|
|
|
var publicKeyRing *crypto.KeyRing
|
|
|
|
|
var pgpMessage *crypto.PGPMessage
|
|
|
|
|
|
|
|
|
|
var message = crypto.NewPlainMessageFromString(plaintext)
|
|
|
|
|
|
2019-12-27 19:35:43 +01:00
|
|
|
if publicKey, err = crypto.NewKeyFromArmored(key); err != nil {
|
|
|
|
|
return "", err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if publicKeyRing, err = crypto.NewKeyRing(publicKey); err != nil {
|
2019-06-03 17:00:01 +02:00
|
|
|
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 plaintext and an armored public key
|
|
|
|
|
// a private key and its passphrase
|
|
|
|
|
func EncryptSignMessageArmored(
|
2019-12-27 19:35:43 +01:00
|
|
|
publicKey, privateKey string, passphrase []byte, plaintext string,
|
2019-06-03 17:00:01 +02:00
|
|
|
) (ciphertext string, err error) {
|
2019-12-27 19:35:43 +01:00
|
|
|
var publicKeyObj, privateKeyObj, unlockedKeyObj *crypto.Key
|
2019-06-03 17:00:01 +02:00
|
|
|
var publicKeyRing, privateKeyRing *crypto.KeyRing
|
|
|
|
|
var pgpMessage *crypto.PGPMessage
|
|
|
|
|
|
|
|
|
|
var message = crypto.NewPlainMessageFromString(plaintext)
|
|
|
|
|
|
2019-12-27 19:35:43 +01:00
|
|
|
if publicKeyObj, err = crypto.NewKeyFromArmored(publicKey); err != nil {
|
|
|
|
|
return "", err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if publicKeyRing, err = crypto.NewKeyRing(publicKeyObj); err != nil {
|
|
|
|
|
return "", err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if privateKeyObj, err = crypto.NewKeyFromArmored(privateKey); err != nil {
|
2019-06-03 17:00:01 +02:00
|
|
|
return "", err
|
|
|
|
|
}
|
|
|
|
|
|
2019-12-27 19:35:43 +01:00
|
|
|
if unlockedKeyObj, err = privateKeyObj.Unlock(passphrase); err != nil {
|
2019-06-03 17:00:01 +02:00
|
|
|
return "", err
|
|
|
|
|
}
|
|
|
|
|
|
2019-12-27 19:35:43 +01:00
|
|
|
if privateKeyRing, err = crypto.NewKeyRing(unlockedKeyObj); err != nil {
|
2019-06-03 17:00:01 +02:00
|
|
|
return "", err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if pgpMessage, err = publicKeyRing.Encrypt(message, privateKeyRing); err != nil {
|
|
|
|
|
return "", err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ciphertext, err = pgpMessage.GetArmored(); err != nil {
|
|
|
|
|
return "", err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ciphertext, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// DecryptMessageArmored decrypts an armored PGP message given a private key and its passphrase
|
|
|
|
|
func DecryptMessageArmored(
|
2019-12-27 19:35:43 +01:00
|
|
|
privateKey string, passphrase []byte, ciphertext string,
|
2019-06-03 17:00:01 +02:00
|
|
|
) (plaintext string, err error) {
|
2019-12-27 19:35:43 +01:00
|
|
|
var privateKeyObj, privateKeyUnlocked *crypto.Key
|
2019-06-03 17:00:01 +02:00
|
|
|
var privateKeyRing *crypto.KeyRing
|
|
|
|
|
var pgpMessage *crypto.PGPMessage
|
|
|
|
|
var message *crypto.PlainMessage
|
|
|
|
|
|
2019-12-27 19:35:43 +01:00
|
|
|
if privateKeyObj, err = crypto.NewKeyFromArmored(privateKey); err != nil {
|
2019-06-03 17:00:01 +02:00
|
|
|
return "", err
|
|
|
|
|
}
|
|
|
|
|
|
2019-12-27 19:35:43 +01:00
|
|
|
if privateKeyUnlocked, err = privateKeyObj.Unlock(passphrase); err != nil {
|
|
|
|
|
return "", err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if privateKeyRing, err = crypto.NewKeyRing(privateKeyUnlocked); err != nil {
|
2019-06-03 17:00:01 +02:00
|
|
|
return "", err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if pgpMessage, err = crypto.NewPGPMessageFromArmored(ciphertext); err != nil {
|
|
|
|
|
return "", err
|
|
|
|
|
}
|
|
|
|
|
|
2019-07-02 07:36:02 -07:00
|
|
|
if message, err = privateKeyRing.Decrypt(pgpMessage, nil, 0); err != nil {
|
2019-06-03 17:00:01 +02:00
|
|
|
return "", err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return message.GetString(), nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// DecryptVerifyMessageArmored decrypts an armored PGP message given a private key and its passphrase
|
|
|
|
|
// and verifies the embedded signature.
|
|
|
|
|
// Returns the plain data or an error on signature verification failure.
|
|
|
|
|
func DecryptVerifyMessageArmored(
|
2019-12-27 19:35:43 +01:00
|
|
|
publicKey, privateKey string, passphrase []byte, ciphertext string,
|
2019-06-03 17:00:01 +02:00
|
|
|
) (plaintext string, err error) {
|
2019-12-27 19:35:43 +01:00
|
|
|
var publicKeyObj, privateKeyObj, unlockedKeyObj *crypto.Key
|
2019-06-03 17:00:01 +02:00
|
|
|
var publicKeyRing, privateKeyRing *crypto.KeyRing
|
|
|
|
|
var pgpMessage *crypto.PGPMessage
|
|
|
|
|
var message *crypto.PlainMessage
|
|
|
|
|
|
2019-12-27 19:35:43 +01:00
|
|
|
if publicKeyObj, err = crypto.NewKeyFromArmored(publicKey); err != nil {
|
2019-06-03 17:00:01 +02:00
|
|
|
return "", err
|
|
|
|
|
}
|
|
|
|
|
|
2019-12-27 19:35:43 +01:00
|
|
|
if publicKeyRing, err = crypto.NewKeyRing(publicKeyObj); err != nil {
|
2019-06-03 17:00:01 +02:00
|
|
|
return "", err
|
|
|
|
|
}
|
|
|
|
|
|
2019-12-27 19:35:43 +01:00
|
|
|
if privateKeyObj, err = crypto.NewKeyFromArmored(privateKey); err != nil {
|
|
|
|
|
return "", err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if unlockedKeyObj, err = privateKeyObj.Unlock(passphrase); err != nil {
|
|
|
|
|
return "", err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if privateKeyRing, err = crypto.NewKeyRing(unlockedKeyObj); err != nil {
|
2019-06-03 17:00:01 +02:00
|
|
|
return "", err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if pgpMessage, err = crypto.NewPGPMessageFromArmored(ciphertext); err != nil {
|
|
|
|
|
return "", err
|
|
|
|
|
}
|
|
|
|
|
|
2019-10-22 18:44:45 +02:00
|
|
|
if message, err = privateKeyRing.Decrypt(pgpMessage, publicKeyRing, crypto.GetUnixTime()); err != nil {
|
2019-06-03 17:00:01 +02:00
|
|
|
return "", err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return message.GetString(), nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// DecryptVerifyAttachment decrypts and verifies an attachment split into the keyPacket, dataPacket
|
|
|
|
|
// and an armored (!) signature, given a publicKey, and a privateKey with its passphrase.
|
|
|
|
|
// Returns the plain data or an error on signature verification failure.
|
|
|
|
|
func DecryptVerifyAttachment(
|
2019-12-27 19:35:43 +01:00
|
|
|
publicKey, privateKey string,
|
|
|
|
|
passphrase, keyPacket, dataPacket []byte,
|
2019-06-03 17:00:01 +02:00
|
|
|
armoredSignature string,
|
|
|
|
|
) (plainData []byte, err error) {
|
2019-12-27 19:35:43 +01:00
|
|
|
var publicKeyObj, privateKeyObj, unlockedKeyObj *crypto.Key
|
2019-06-03 17:00:01 +02:00
|
|
|
var publicKeyRing, privateKeyRing *crypto.KeyRing
|
|
|
|
|
var detachedSignature *crypto.PGPSignature
|
|
|
|
|
var message *crypto.PlainMessage
|
|
|
|
|
|
|
|
|
|
var packets = crypto.NewPGPSplitMessage(keyPacket, dataPacket)
|
|
|
|
|
|
2019-12-27 19:35:43 +01:00
|
|
|
if publicKeyObj, err = crypto.NewKeyFromArmored(publicKey); err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if publicKeyRing, err = crypto.NewKeyRing(publicKeyObj); err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if privateKeyObj, err = crypto.NewKeyFromArmored(privateKey); err != nil {
|
2019-06-03 17:00:01 +02:00
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
|
2019-12-27 19:35:43 +01:00
|
|
|
if unlockedKeyObj, err = privateKeyObj.Unlock(passphrase); err != nil {
|
2019-06-03 17:00:01 +02:00
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
|
2019-12-27 19:35:43 +01:00
|
|
|
if privateKeyRing, err = crypto.NewKeyRing(unlockedKeyObj); err != nil {
|
2019-06-03 17:00:01 +02:00
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if detachedSignature, err = crypto.NewPGPSignatureFromArmored(armoredSignature); err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if message, err = privateKeyRing.DecryptAttachment(packets); err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
|
2019-10-22 18:44:45 +02:00
|
|
|
if publicKeyRing.VerifyDetached(message, detachedSignature, crypto.GetUnixTime()) != nil {
|
2019-06-03 17:00:01 +02:00
|
|
|
return nil, errors.New("gopenpgp: unable to verify attachment")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return message.GetBinary(), nil
|
|
|
|
|
}
|