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

@ -47,7 +47,7 @@ func (keyRing *KeyRing) SignDetached(message *PlainMessage) (*PGPSignature, erro
config := &packet.Config{DefaultHash: crypto.SHA512, Time: getTimeGenerator()} config := &packet.Config{DefaultHash: crypto.SHA512, Time: getTimeGenerator()}
var outBuf bytes.Buffer var outBuf bytes.Buffer
//sign bin // sign bin
if err := openpgp.DetachSign(&outBuf, signEntity, message.NewReader(), config); err != nil { if err := openpgp.DetachSign(&outBuf, signEntity, message.NewReader(), config); err != nil {
return nil, err return nil, err
} }

View file

@ -85,6 +85,6 @@ func VerifyCleartextMessage(keyRing *crypto.KeyRing, armored string, verifyTime
// canonicalizeAndTrim alters a string canonicalizing and trimming the newlines. // canonicalizeAndTrim alters a string canonicalizing and trimming the newlines.
func canonicalizeAndTrim(text string) string { func canonicalizeAndTrim(text string) string {
text = internal.TrimNewlines(text) 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 return text
} }

View file

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

View file

@ -84,8 +84,8 @@ type EncryptSignArmoredDetachedMobileResult struct {
Ciphertext, Signature string Ciphertext, Signature string
} }
//EncryptSignArmoredDetachedMobile wraps the EncryptSignArmoredDetached method // EncryptSignArmoredDetachedMobile wraps the EncryptSignArmoredDetached method
//to have only one return argument for mobile. // to have only one return argument for mobile.
func EncryptSignArmoredDetachedMobile( func EncryptSignArmoredDetachedMobile(
publicKey, privateKey string, publicKey, privateKey string,
passphrase, plainData []byte, passphrase, plainData []byte,