passforios-gopenpgp/helper/helper.go
zugzwang ac8a49c114
Update lint (#44)
* Reduce complexity of SignatureCollector.Accept

* Add stylecheck linter, and lint accordingly

* Rephrase some comments

* godot - Top level comments should end with a dot.

* nestif - Reduce nested complexity of code

* Review changes

Co-authored-by: Aron Wussler <aron@wussler.it>
2020-04-28 13:55:36 +02:00

242 lines
6.9 KiB
Go

// Package helper contains several functions with a simple interface to extend usability and compatibility with gomobile
package helper
import (
"errors"
"github.com/ProtonMail/gopenpgp/v2/crypto"
)
// EncryptMessageWithPassword encrypts a string with a passphrase using AES256.
func EncryptMessageWithPassword(password []byte, plaintext string) (ciphertext string, err error) {
var pgpMessage *crypto.PGPMessage
var message = crypto.NewPlainMessageFromString(plaintext)
if pgpMessage, err = crypto.EncryptMessageWithPassword(message, password); err != nil {
return "", err
}
if ciphertext, err = pgpMessage.GetArmored(); err != nil {
return "", err
}
return ciphertext, nil
}
// DecryptMessageWithPassword decrypts an armored message with a random token.
// The algorithm is derived from the armoring.
func DecryptMessageWithPassword(password []byte, ciphertext string) (plaintext string, err error) {
var message *crypto.PlainMessage
var pgpMessage *crypto.PGPMessage
if pgpMessage, err = crypto.NewPGPMessageFromArmored(ciphertext); err != nil {
return "", err
}
if message, err = crypto.DecryptMessageWithPassword(pgpMessage, password); err != nil {
return "", err
}
return message.GetString(), nil
}
// 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
}
// EncryptSignMessageArmored generates an armored signed PGP message given a
// plaintext and an armored public key a private key and its passphrase.
func EncryptSignMessageArmored(
publicKey, privateKey string, passphrase []byte, plaintext string,
) (ciphertext string, err error) {
var publicKeyObj, privateKeyObj, unlockedKeyObj *crypto.Key
var publicKeyRing, privateKeyRing *crypto.KeyRing
var pgpMessage *crypto.PGPMessage
var message = crypto.NewPlainMessageFromString(plaintext)
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 {
return "", err
}
if unlockedKeyObj, err = privateKeyObj.Unlock(passphrase); err != nil {
return "", err
}
defer unlockedKeyObj.ClearPrivateParams()
if privateKeyRing, err = crypto.NewKeyRing(unlockedKeyObj); err != nil {
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(
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
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 {
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(
publicKey, privateKey string, passphrase []byte, ciphertext string,
) (plaintext string, err error) {
var publicKeyObj, privateKeyObj, unlockedKeyObj *crypto.Key
var publicKeyRing, privateKeyRing *crypto.KeyRing
var pgpMessage *crypto.PGPMessage
var message *crypto.PlainMessage
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 {
return "", err
}
if unlockedKeyObj, err = privateKeyObj.Unlock(passphrase); err != nil {
return "", err
}
defer unlockedKeyObj.ClearPrivateParams()
if privateKeyRing, err = crypto.NewKeyRing(unlockedKeyObj); err != nil {
return "", err
}
if pgpMessage, err = crypto.NewPGPMessageFromArmored(ciphertext); err != nil {
return "", err
}
if message, err = privateKeyRing.Decrypt(pgpMessage, publicKeyRing, crypto.GetUnixTime()); err != nil {
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(
publicKey, privateKey string,
passphrase, keyPacket, dataPacket []byte,
armoredSignature string,
) (plainData []byte, err error) {
var publicKeyObj, privateKeyObj, unlockedKeyObj *crypto.Key
var publicKeyRing, privateKeyRing *crypto.KeyRing
var detachedSignature *crypto.PGPSignature
var message *crypto.PlainMessage
var packets = crypto.NewPGPSplitMessage(keyPacket, dataPacket)
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 {
return nil, err
}
if unlockedKeyObj, err = privateKeyObj.Unlock(passphrase); err != nil {
return nil, err
}
defer unlockedKeyObj.ClearPrivateParams()
if privateKeyRing, err = crypto.NewKeyRing(unlockedKeyObj); err != nil {
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
}
if publicKeyRing.VerifyDetached(message, detachedSignature, crypto.GetUnixTime()) != nil {
return nil, errors.New("gopenpgp: unable to verify attachment")
}
return message.GetBinary(), nil
}