Additional helpers for iOS drive (#78)

* add tests

Co-authored-by: wussler <aron@wussler.it>
Co-authored-by: marin thiercelin <marin.thiercelin@pm.me>
This commit is contained in:
marinthiercelin 2020-09-11 15:35:22 +02:00 committed by GitHub
parent 64b3b45404
commit 55c4bd994d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 174 additions and 48 deletions

View file

@ -85,6 +85,6 @@ func VerifyCleartextMessage(keyRing *crypto.KeyRing, armored string, verifyTime
// canonicalizeAndTrim alters a string canonicalizing and trimming the newlines.
func canonicalizeAndTrim(text string) string {
text = internal.TrimNewlines(text)
text = strings.Replace(strings.Replace(text, "\r\n", "\n", -1), "\n", "\r\n", -1)
text = strings.ReplaceAll(strings.ReplaceAll(text, "\r\n", "\n"), "\n", "\r\n")
return text
}

View file

@ -52,23 +52,13 @@ func EncryptMessageArmored(key, plaintext string) (string, error) {
func EncryptSignMessageArmored(
publicKey, privateKey string, passphrase []byte, plaintext string,
) (ciphertext string, err error) {
var publicKeyObj, privateKeyObj, unlockedKeyObj *crypto.Key
var 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 publicKeyObj.IsPrivate() {
publicKeyObj, err = publicKeyObj.ToPublic()
if err != nil {
return "", err
}
}
if publicKeyRing, err = crypto.NewKeyRing(publicKeyObj); err != nil {
if publicKeyRing, err = createPublicKeyRing(publicKey); err != nil {
return "", err
}
@ -116,22 +106,12 @@ func DecryptMessageArmored(
func DecryptVerifyMessageArmored(
publicKey, privateKey string, passphrase []byte, ciphertext string,
) (plaintext string, err error) {
var publicKeyObj, privateKeyObj, unlockedKeyObj *crypto.Key
var 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 publicKeyObj.IsPrivate() {
publicKeyObj, err = publicKeyObj.ToPublic()
if err != nil {
return "", err
}
}
if publicKeyRing, err = crypto.NewKeyRing(publicKeyObj); err != nil {
if publicKeyRing, err = createPublicKeyRing(publicKey); err != nil {
return "", err
}
@ -256,20 +236,79 @@ func DecryptVerifyArmoredDetached(
return message.GetBinary(), nil
}
// EncryptAttachmentWithKey encrypts a binary file
// Using a given armored public key.
func EncryptAttachmentWithKey(
publicKey string,
filename string,
plainData []byte,
) (message *crypto.PGPSplitMessage, err error) {
publicKeyRing, err := createPublicKeyRing(publicKey)
if err != nil {
return nil, err
}
return EncryptAttachment(plainData, filename, publicKeyRing)
}
// DecryptAttachmentWithKey decrypts a binary file
// Using a given armored private key and its passphrase.
func DecryptAttachmentWithKey(
privateKey string,
passphrase, keyPacket, dataPacket []byte,
) (attachment []byte, err error) {
message, err := decryptAttachment(privateKey, passphrase, keyPacket, dataPacket)
if err != nil {
return nil, err
}
return message.GetBinary(), nil
}
// EncryptSessionKey encrypts a session key
// using a given armored public key.
func EncryptSessionKey(
publicKey string,
sessionKey *crypto.SessionKey,
) (encryptedSessionKey []byte, err error) {
publicKeyRing, err := createPublicKeyRing(publicKey)
if err != nil {
return nil, err
}
encryptedSessionKey, err = publicKeyRing.EncryptSessionKey(sessionKey)
return
}
// DecryptSessionKey decrypts a session key
// using a given armored private key
// and its passphrase.
func DecryptSessionKey(
privateKey string,
passphrase, encryptedSessionKey []byte,
) (sessionKey *crypto.SessionKey, err 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
}
sessionKey, err = privateKeyRing.DecryptSessionKey(encryptedSessionKey)
return
}
func encryptMessageArmored(key string, message *crypto.PlainMessage) (string, error) {
publicKey, err := crypto.NewKeyFromArmored(key)
if publicKey.IsPrivate() {
publicKey, err = publicKey.ToPublic()
if err != nil {
return "", err
}
}
if err != nil {
return "", err
}
publicKeyRing, err := crypto.NewKeyRing(publicKey)
publicKeyRing, err := createPublicKeyRing(key)
if err != nil {
return "", err
@ -363,22 +402,14 @@ func signDetachedArmored(privateKey string, passphrase []byte, message *crypto.P
}
func verifyDetachedArmored(publicKey string, message *crypto.PlainMessage, armoredSignature string) (check bool, err error) {
var publicKeyObj *crypto.Key
var publicKeyRing *crypto.KeyRing
var detachedSignature *crypto.PGPSignature
// We prepare the public key for signature verification
if publicKeyObj, err = crypto.NewKeyFromArmored(publicKey); err != nil {
return false, err
}
if publicKeyObj.IsPrivate() {
publicKeyObj, err = publicKeyObj.ToPublic()
publicKeyRing, err = createPublicKeyRing(publicKey)
if err != nil {
return false, err
}
}
if publicKeyRing, err = crypto.NewKeyRing(publicKeyObj); err != nil {
return false, err
}
// We verify the signature
if detachedSignature, err = crypto.NewPGPSignatureFromArmored(armoredSignature); err != nil {
@ -418,3 +449,23 @@ func decryptAttachment(
return message, nil
}
func createPublicKeyRing(
publicKey string,
) (publicKeyRing *crypto.KeyRing, err error) {
publicKeyObj, err := crypto.NewKeyFromArmored(publicKey)
if err != nil {
return nil, err
}
if publicKeyObj.IsPrivate() {
publicKeyObj, err = publicKeyObj.ToPublic()
if err != nil {
return nil, err
}
}
publicKeyRing, err = crypto.NewKeyRing(publicKeyObj)
return
}

View file

@ -216,3 +216,78 @@ func TestEncryptSignArmoredDetached(t *testing.T) {
t.Fatal("Expected an error while decrypting and verifying with a wrong signature")
}
}
func TestEncryptDecryptAttachmenWithKey(t *testing.T) {
plainData := []byte("Secret message")
privateKeyString := readTestFile("keyring_privateKey", false)
privateKey, err := crypto.NewKeyFromArmored(privateKeyString)
if err != nil {
t.Fatal("Error reading the test private key: ", err)
}
publicKeyString, err := privateKey.GetArmoredPublicKey()
if err != nil {
t.Fatal("Error reading the test public key: ", err)
}
pgpSplitMessage, err := EncryptAttachmentWithKey(
publicKeyString,
"test_filename",
plainData,
)
if err != nil {
t.Fatal("Expected no error while encrypting, got:", err)
}
decrypted, err := DecryptAttachmentWithKey(
privateKeyString,
testMailboxPassword,
pgpSplitMessage.KeyPacket,
pgpSplitMessage.DataPacket,
)
if err != nil {
t.Fatal("Expected no error while decrypting, got:", err)
}
if !bytes.Equal(decrypted, plainData) {
t.Error("Decrypted attachment is not equal to the original attachment")
}
}
func TestEncryptDecryptSessionKey(t *testing.T) {
privateKeyString := readTestFile("keyring_privateKey", false)
privateKey, err := crypto.NewKeyFromArmored(privateKeyString)
if err != nil {
t.Fatal("Error reading the test private key: ", err)
}
publicKeyString, err := privateKey.GetArmoredPublicKey()
if err != nil {
t.Fatal("Error reading the test public key: ", err)
}
sessionKey, err := crypto.GenerateSessionKeyAlgo("aes256")
if err != nil {
t.Fatal("Expected no error while generating the session key, got:", err)
}
encrypted, err := EncryptSessionKey(publicKeyString, sessionKey)
if err != nil {
t.Fatal("Expected no error while encrypting session key, got:", err)
}
decryptedSessionKey, err := DecryptSessionKey(
privateKeyString,
testMailboxPassword,
encrypted,
)
if err != nil {
t.Fatal("Expected no error while decrypting session key, got:", err)
}
if decryptedSessionKey.GetBase64Key() != sessionKey.GetBase64Key() {
t.Error("Decrypted session key is not equal to the original session key")
}
}