I'm using Apple's CryptoKit to create keys for an iOS app, encrypt the data and then send it to the backend via JSON and store it in a PGSQL database.
While all of that is working perfectly, I need to be able to decrypt the data from the backend, and thus need to be able to create the same symmetric key I used to encrypt the data.
When I created the keys via Swift, it was done as follows:
let privateKey = Curve25519.KeyAgreement.PrivateKey()
let publicKey = privateKey.publicKey
let sharedSecret = try! privateKey.sharedSecretFromKeyAgreement(with: publicKey)
let symmetricKey = sharedSecret.hkdfDerivedSymmetricKey(using: SHA512.self,
salt: "\(vhvioerhvoreovjreoivgifjtughrygryrufejewdf))".data(using: .utf8)!,
sharedInfo: Data(),
outputByteCount: 32)
Note: The salt is just me typing a bunch of random characters for this example code, but you get the idea.
I need to accomplish the same thing using Python. The keys are base64 encoded strings sent via JSON to the backend as well so I need to do a b64decode on them (which I've already got working).
I tried using pynacl but I cannot figure out how to create the symmetric key, using sha512 and the same salt I used to create the symmetric key in Swift. I am also in no way tied to pynacl if there's a better option.
Again, the above code is just an example of the process used to create a private, public, and symmetric key in Swift. I am actually using a public key from one account, with a private key from another to create the symmetric key and encrypt the data. I will be doing the same in reverse to decrypt (i.e. a public key from the private key account, and a private key from the public key account).
So far, playing around with it in python I have the following (but again, I am not tied to pynacl if there's a better solution):
from nacl.public import Box, PrivateKey, PublicKey, SealedBox
from nacl.hash import sha512
import nacl.encoding
from base64 import b64decode, b64encode
import binascii
privKeyRead = b64decode('uBruInrnbtrberverv6XZZqQDDeS4SwORSHriW04=')
private_key = PrivateKey(privKeyRead)
pubKeyRead = b64decode('UIZSc3QBfewojfoewjgowjgCqA/P8PjXDlQwU7rTHFBw=')
public_key = PublicKey(pubKeyRead)
salt = b64decode('HIHIUGUBLJOIHIBIOHO9nM0NSSkNDejUwcXJMNUdlUT0=')
cryptoBox = Box(private_key, public_key)
sharedSecret = Box.shared_key(cryptoBox)
# Print Keys and Salt
print("Private Key:", privKeyRead)
print("Public Key:", pubKeyRead)
print("Salt:", salt)
print("Crypto Box:", cryptoBox)
print("Shared Secret:", sharedSecret)
return printed
Note: The privKeyRead, pubKeyRead, and salt values have garbage characters for this example as I can't obviously post the real values. I have also noticed that both the Crypto Box and the Shared Secret are identical, so I'm pretty sure I would only need one and not both.
Lastly, and I don't want anyone to get hung up on this, I am using Zope5 which is why you see my python example as it is. This is a python script in zope which is perfectly valid. I can also create external methods, so if you have functions, etc. that will work better, please feel free to post exactly how you would do it where zope isn't in the equation. I'll reconfigure for zope if necessary.