I have a C library I need to use in my Swift code and a function thet expects an UnsafeMutablePointer<UInt8>
that is 32 bytes long to generate a public key from an existing private key (crypto_sign_public_key
). Here is a link to the docs of the C function I am calling: https://monocypher.org/manual/sign. I don't have much experience with C and pointers but I've read a few tutorials and have something that seems to be working perfectly.
Aside from that though, I wanted to see if anyone with more experience than me might be able to say if this code is "safe" and/or will potentially produce undefined behaviour?
func generatePublicKey(from privateKey: [UInt8]) -> [UInt8] {
/// Create an empty pointer that is 32 bytes long. The resulting public key will be written to the memory the pointer is pointing to.
let publicKeyPointer = UnsafeMutablePointer<UInt8>.allocate(capacity: 32)
/// This is using the 25519 curve and the Blake2b hash method.
/// Sign the private key and in turn, create the public key.
crypto_sign_public_key(publicKeyPointer, privateKey)
/// Go over the 32 bytes of the pointer and save it's locations as a "buffer"
let buffer = UnsafeMutableBufferPointer(start: publicKeyPointer, count: 32)
/// Copy the data being pointed to, into an actual array.
let publicKey = Array(buffer)
/// Deallocate the memory being used by the pointer.
publicKeyPointer.deallocate()
return publicKey
}
Thank you!
Your code is okay, because UInt8
is a trivial type and so doesn't require that you call initialize
or deinitialize
on the allocated memory.
However, you can avoid the manual allocation and deallocation entirely, like this:
func makePublicKey(withPrivateKey privateKey: [UInt8]) -> [UInt8] {
var publicKey = [UInt8](repeating: 0, count: 32)
publicKey.withUnsafeMutableBufferPointer { buffer in
crypto_sign_public_key(buffer.baseAddress!, privateKey)
}
return publicKey
}