Generate a symmetric key on iOS using Security.framework - ios

I'm struggling to generate a symmetric key in iOS using the security framework. There is a method SecKeyGenerateSymmetric() in SecKey.h but its for macOS only. The only thing I see available is SecKeyGeneratePair() which is for asymmetric encryption.
Also from reading this documentation it looks the only way to do symmetric encryption is by generating an asymmetric key pair and calling SecKeyCreateEncryptedData() with the public key and behind the scenes a symmetric key is generated but you don't have access to it. I need to have access to the symmetric key.
If anyone has experience doing symmetric encryption on iOS I would be grateful of some guidance.

With CryptoKit's introduction this can be done using the following code:
import CryptoKit
//generate Symmetric key
let key = SymmetricKey(size: .bits256)
Here is an example using AES-GCM method for encrypting and decrypting using the 32 byte symmetric key:
//generate Symmetric key
let key = SymmetricKey(size: .bits256)
//encrypt plaintext
let encryptedData = try! AES.GCM.seal("plain-text".data(using: .utf8)!, using: key)
print("Encrypted data using symmetric key:\(encryptedData)")
//decrypt data
let sealedBoxRestored = try! AES.GCM.SealedBox(nonce: encryptedData.nonce, ciphertext: encryptedData.ciphertext, tag: encryptedData.tag)
let decryptedData = try! AES.GCM.open(sealedBoxRestored, using: key)
print("Decrypted:\n\(String(data: decryptedData, encoding: .utf8)!)")

Related

ECIES encryption and EC key generation in Swift

Backend uses this java implementation for encrypting the data using public key(generated from iOS App in swift),
Cipher iesCipher = Cipher.getInstance("ECIESwithAES-CBC");
byte[] derivation = Hex.decode(derivationString);
byte[] encoding = Hex.decode(encodingString);
byte[] nonce = Hex.decode(nonceString);
IESParameterSpec params = new IESParameterSpec(derivation, encoding, 128, 128, nonce, true);
iesCipher.init(Cipher.ENCRYPT_MODE, publicKey, params);
byte[] ciphertext = iesCipher.doFinal(data.getBytes());
But in swift I could not find any equivalent library to decrypt it. I am using the SwiftECC for generating the EC key-pair and sending the public key to server. Then server encrypts the data using that public key as mentioned in above implementation code. But SwiftECC has no any decrypt function which accepts the arguments like derivation, encoding, nonce. And I could not find anything similar to above java implementation in swift.
ECIES is using ephemeral static-ECDH + key derivation + encryption, where the public key of the ephemeral key pair is stored with the ciphertext. So if you find ECDH + the right key derivation + AES-CBC encryption (probably using PKCS#7 padding) then you'd be in business. Apparently BC uses KDF2 with SHA-1 for key derivation. I've asked and answered what KDF2 is here.
I’ve implemented ECIES in EllipticCurveKit, feel free to use it as inspiration. Should be straightening enough to port it to SwiftECC if you don’t want to use EllipticCurveKits EC implementation.
I've hard coded the curve to be Secp256k1 (aka "the bitcoin curve"), but you could easily make it generic, by passing in a generic Curve type, just change:
func seal<Plaintext>(
_ message: Plaintext,
whitePublicKey: PublicKey<Secp256k1>,
blackPrivateKey: PrivateKey<Secp256k1>,
nonce: SealedBox.Nonce? = nil
) -> Result<SealedBox, EncryptionError> where Plaintext: DataProtocol
into (which should work in EllipticCurveKit, and should be possible in other EC libs too):
func seal<Plaintext, Curve>(
_ message: Plaintext,
whitePublicKey: PublicKey<Curve>,
blackPrivateKey: PrivateKey<Curve>,
nonce: SealedBox.Nonce? = nil
) -> Result<SealedBox, EncryptionError> where Plaintext: DataProtocol, Curve: EllipticCurve

Encrypting in Rails and decrypting in Salesforce

I'm using the attr_encrypted gem in a Rails project and encrypting bank account numbers in a PostgreSQL database. In the database, I have two columns (encrypted_bank_account and encrypted_bank_account_iv) that are used for the encrypted data. I have this line in my payment_method model file:
attr_encrypted :account_number, key: ENV['ACCOUNT_KEY'], encode: true, encode_iv: true, algorithm: 'aes-256-cbc'
I want to be able to send this encrypted data to SalesForce, decrypt it, and store it in a SalesForce object. I'm not exactly sure how to decrypt it when it gets there and could use some advice. Thanks!
Have an endpoint on salesforce that takes the data and decrypts it in
// Normally this key should be stored in a protected custom setting
// or an encrypted field on a custom object
Blob cryptoKey = Crypto.generateAesKey(256);
// Generate the data to be encrypted.
Blob data = Blob.valueOf('Test data to encrypted');
// Encrypt the data and have Salesforce.com generate the initialization vector
Blob encryptedData = Crypto.encryptWithManagedIV('AES256', cryptoKey, data);
// Decrypt the data - the first 16 bytes contain the initialization vector
Blob decryptedData = Crypto.decryptWithManagedIV('AES256', cryptoKey, encryptedData);
// Decode the decrypted data for subsequent use
String decryptedDataString = decryptedData.toString();
https://developer.salesforce.com/page/Apex_Crypto_Class

Load and use PKCS#8 Private Key

I am currently generating and saving a key pair of RSA keys inside a Java REST Server using the following block of code:
keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(2048);
KeyPair keyPair = keyPairGenerator.genKeyPair();
publicKey=keyPair.getPublic();
publicKeyBase64 = Base64.encodeBase64String(publicKey.getEncoded()) ;
PrivateKey privateKey = keyPair.getPrivate();
privateKeyBase64 = Base64.encodeBase64String(privateKey.getEncoded());
Now I want to use this same private key to decrypt another information returned from the server using an iOS client. As far as I know, the iOS does not provide great native support for RSA encryption. How can I decrypt information using this private key, supposing that I currently have the key encoded as a PKCS#8 Base64 string (like inside the variable privateKeyBase64)?
Thank you!

Is there any Elliptic Curve algorithm equivalent to RSA's asymmetric encryption?

I've been searching but I cant find anything about this... only EC Diffie-Hellman with symmetric cryptography, which is exactly what I do not want :(
Imagine this:
generate a random private key, k
then calculate a "public key" with ECC, d=kG
The algorithm I'm looking for is this: any message cyphered with the public key will "only" be decyphered by the owner of the private key.
Does this exists? Has anything like this been developed yet?
You could try ecc (pip install ecc)
from ecc.Key.Key import Key
# Create keypair
k=Key.generate(521)
# Encode public key
pub=k.encode()
# Encode private key
priv=k.encode(include_private=True)
# Decode public key
pubK=Key.decode(pub)
# Decode private key
privK=Key.decode(priv)
# Encrypt message
msg=pubK.encrypt("Test")
# Decrypt message
print privK.decrypt(msg)
Actually, El Gamal scheme, being based on Diffie–Hellman key exchange, presumes an asymmetric encryption algorithm, with private and public keys, so you should consider this. Computing the public key in this scheme will be as difficult as computing the discrete logarithm in the group.

Codesigning SWF?

AIR allows to inject code using Loader.LoadBytes()
this allows to download remote plugins as swf files which will have full access to everything that the AIR application has access to. This imposes a security risk, so it would be desirable to digitally sign the swf's.
What's the best way to do this and to verify the code signature?
I know the as3corelib has some encryption functionality and also for X.509 certificate - but I didn't find a ressource explaining how to use it. Also, maybe there's some 'official' way to codesign SWF's?
One robust method is using public key encryption, which goes something like this:
You will need an asymmetric encryption algorithm (eg, RSA), and a hash algorithm (eg, SHA, MD5).
Generate a public-private key pair.
Generate and checksum of the data using the hash algorithm.
Encrypt the checksum with the private key using the encryption algorithm. This becomes the "signature".
Send the data to the client along with the signature.
Decrypt the signature on the client with the public key to obtain the original checksum.
Generate a checksum from the data on the client.
Compare the checksums. If they match, then you know that the data came from you without alterations. If they do not match then you know the data was altered after it was sent from you, or it came from someone else.
See http://en.wikipedia.org/wiki/Public-key_cryptography
An attacker can bypass this security if they are able to intercept the connection and modify the original client SWF file and either change the public key, or remove the security mechanism entirely. Use TLS or SSL to prevent attackers intercepting the data.
An x.509 certificate is little more than a public key bundled with some meta-data. The standard also specifies a mechanism for validating the certificate, by relying on a certificate authority (CA) (see http://en.wikipedia.org/wiki/X.509).
The AS3Crypto library provides (amongst other things), an implementation of RSA, MD5, and an x.509 parser (see http://code.google.com/p/as3crypto/).
Here is some code. The signing process entails computing the hash of the data, then signing it with the private key to produce a signature, eg:
var rsa:RSAKey;
var md5:MD5;
var data:ByteArray = getSWFBytes();
var signature:ByteArray = new ByteArray();
var originalHash:ByteArray;
// read private key
rsa = PEM.readRSAPrivateKey(private_key);
// create the checksum of the original data
md5 = new MD5();
originalHash = md5.hash(original);
// encrypt the data using the private key
rsa.sign(data, signature, original.length);
The data and signature are sent to the client. The client decrypts the signature using the public key stored in the cert and compare it to the computed hash of the data, eg:
var rsa:RSAKey;
var md5:MD5;
var data:ByteArray = getSWFBytes();
var signature:ByteArray = new ByteArray();
var decryptedHash:ByteArray = new ByteArray();
var clientHash:ByteArray;
// load the certificate
var cert:X509Certificate = new X509Certificate(public_cert);
// get the public key from the cert
rsa = cert.getPublicKey();
// decrypt the signature with the public key
rsa.verify(signature, decryptedHash, encrypted.length);
// create a hash of the data
md5 = new MD5();
clientHash = md5.hash(data);
// compare the hashes
// isEqual compares the bytes in the input byte arrays, it returns true only of all bytes in both arrays match
if (isEqual(clientHash, decryptedHash))
trace("signature valid");
else
trace("signature invalid")
You can check if the certificate is signed like this:
var store:X509CertificateCollection = new MozillaRootCertificates();
var cert:X509Certificate = new X509Certificate(public_cert);
var isValid:Boolean = cert.isSigned(store, store);
You can load the raw SWF bytes like this:
var loader:URLLoader = new URLLoader();
loader.dataFormat = URLLoaderDataFormat.BINARY;
loader.addEventListener(Event.COMPLETE, completeHandler);
loader.load(new URLRequest(url_of_swf_to_load));
Example x.509 private key (usually created when you apply for a certificate):
-----BEGIN RSA PRIVATE KEY-----
MIICWwIBAAKBgQDoKlLzpJeLcoPYQQYPa0diM4zpZ+0rKeRxhx9ssq91DzwAeSmM
7wT03WLiLZkqPt2MS3uNo75zK5RtmjHqF6Ojfs2tbSdlCK5tpisvOAssuq0o5vIz
g/MhS2PIijnBtVB9XFSTXxhveKeIq1VgdB2wHW95+zhBF+Z1hsYcNRRFFwIDAQAB
AoGAI8wK2EhjmXvBuoFkJtJ6wjiCnKaKmiIueBbGkKMIjLsZnFUSRAnCsOLF0WwI
dswUqwIkfdVmkymADFo/IgIdF9hLGNLRskIPKGZWEUC8d5ZJnRg+nuzi2c2msN5u
/BvCCgL5/shBhO5KvrPbU/Fbs/k4saCDQZ2EO4HpueRZWGkCQQD6hC0pTfyW4yQT
Qr/dY7FhOwdOh/8ewGyXBa9ruOuZqTR23Ya20O8NuF22+NqW9AZl7uioiTZyZkOV
jqAckelrAkEA7T9QVdK+QcaQSznrZPJpXlSIDLSBRWjaPKBoypnNTF3y3JkUQE0L
iA0c2oUc8D+LCgx9vA0Ai0IzwzrIec+iBQJAJb5YV4rKbalXPBeodKCajv2nwis3
QtjXA4H1xhMcXBBkOSxzKYQdIEIQzIp91JR7ikwOfaX+sAm8UQImGWfadQJAMAb4
KVePQluDDGd+OqJEKF9uZzwHS1jNjSZf8FuwTrxaFMQ8cEPoiLM22xnFYPFMIU2k
CnSLXqWZOvVkbhxVTQJAL3xIc5AUbhsEp7ZeeJrkPRv5rCObmLw0+wIaERtMX83b
PNM0TpzY6EXk+geTCqudAipYF/A7qn38wpOh+PuuVg==
-----END RSA PRIVATE KEY-----
Example cert:
-----BEGIN CERTIFICATE-----
MIID4zCCA0ygAwIBAgIJAL7k5X3sCvniMA0GCSqGSIb3DQEBBQUAMIGoMQswCQYD
VQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTERMA8GA1UEBxMIU2FuIEpvc2Ux
FDASBgNVBAoTC2h1cmxhbnQuY29tMRcwFQYDVQQLEw5hczMgY3J5cHRvIGxpYjEY
MBYGA1UEAxMPSGVucmkgVG9yZ2VtYW5lMSgwJgYJKoZIhvcNAQkBFhloZW5yaV90
b3JnZW1hbmVAeWFob28uY29tMB4XDTA3MTEwNTA1MjUyOVoXDTA4MTEwNDA1MjUy
OVowgagxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMREwDwYDVQQH
EwhTYW4gSm9zZTEUMBIGA1UEChMLaHVybGFudC5jb20xFzAVBgNVBAsTDmFzMyBj
cnlwdG8gbGliMRgwFgYDVQQDEw9IZW5yaSBUb3JnZW1hbmUxKDAmBgkqhkiG9w0B
CQEWGWhlbnJpX3RvcmdlbWFuZUB5YWhvby5jb20wgZ8wDQYJKoZIhvcNAQEBBQAD
gY0AMIGJAoGBAOgqUvOkl4tyg9hBBg9rR2IzjOln7Ssp5HGHH2yyr3UPPAB5KYzv
BPTdYuItmSo+3YxLe42jvnMrlG2aMeoXo6N+za1tJ2UIrm2mKy84Cyy6rSjm8jOD
8yFLY8iKOcG1UH1cVJNfGG94p4irVWB0HbAdb3n7OEEX5nWGxhw1FEUXAgMBAAGj
ggERMIIBDTAdBgNVHQ4EFgQU/XyNp2QghYm3MWOU5YoUoFWcTKMwgd0GA1UdIwSB
1TCB0oAU/XyNp2QghYm3MWOU5YoUoFWcTKOhga6kgaswgagxCzAJBgNVBAYTAlVT
MRMwEQYDVQQIEwpDYWxpZm9ybmlhMREwDwYDVQQHEwhTYW4gSm9zZTEUMBIGA1UE
ChMLaHVybGFudC5jb20xFzAVBgNVBAsTDmFzMyBjcnlwdG8gbGliMRgwFgYDVQQD
Ew9IZW5yaSBUb3JnZW1hbmUxKDAmBgkqhkiG9w0BCQEWGWhlbnJpX3RvcmdlbWFu
ZUB5YWhvby5jb22CCQC+5OV97Ar54jAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEB
BQUAA4GBABsXUJjiRAz+FeiVq4JMSBWeiiGcXTw+8sNv8SfWaWx3su+AgooKlBn3
nsGKf3BEDdmJCOSgY0+A5Pce9SRoAMhabHKwoLEogrtp2p8vRj2OTMjWBW7ylrxj
FvUpFdc8qFaqTtgH6+JiIYllGFlcsSV+6d9fDPaFDZEHjz5GweWJ
-----END CERTIFICATE-----
Both examples were taken from as3crypto.

Resources