Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Swift] how can I use signal_aes256_gcm_decryption_new in ffi #477

Closed
JuyeonYu opened this issue Jun 30, 2022 · 2 comments
Closed

[Swift] how can I use signal_aes256_gcm_decryption_new in ffi #477

JuyeonYu opened this issue Jun 30, 2022 · 2 comments

Comments

@JuyeonYu
Copy link

hello.
I am struggling to use libSignal for Swift.
after x3dh, now I get the key for encrypt and decrypt.
So I am ready kdf message key, nonce, tag, and aead.

For encrypt and decrypt, we decided to use
public static native void Aes256GcmDecryption_Update(long gcm, byte[] data, int offset, int length);
public static native void Aes256GcmEncryption_Update(long gcm, byte[] data, int offset, int length);
in java.

Q1. is signal_aes256_gcm_decryption_new in ffi function same as above java function?

SignalFfiError *signal_aes256_gcm_decryption_new(SignalAes256GcmDecryption **out,
SignalBorrowedBuffer key,
SignalBorrowedBuffer nonce,
SignalBorrowedBuffer associated_data);

SignalFfiError *signal_aes256_gcm_decryption_update(SignalAes256GcmDecryption *gcm,
SignalBorrowedMutableBuffer data,
uint32_t offset,
uint32_t length);

SignalFfiError *signal_aes256_gcm_decryption_verify_tag(bool *out,
SignalAes256GcmDecryption *gcm,
SignalBorrowedBuffer tag);

if so, could you give me a sample source how to use the function?

@jrose-signal
Copy link
Contributor

These are general-purpose AES-256-GCM APIs that we haven't finished hooking up to Swift; though they should work as C functions, the C interface is considered an implementation detail and may change from release to release without notice. (But you probably already know that.) The signal_aes256_gcm_decryption_update C function is equivalent to the Java function you pasted (twice, presumably that was an accident). But…are you using this to implement the Signal protocol? LibSignal exposes higher-level operations for that.


That said, the usage from C would be something like

SignalFfiError *error;
SignalAes256GcmDecryption *decrypt;
error = signal_aes256_gcm_decryption_new(&decrypt, key, nonce, associatedDataFromWhenYouEncrypted);
if (error) { return NULL; }

error = signal_aes256_gcm_decryption_update(decrypt, message, 0, message.length); // modifies 'message'
if (error) { return NULL; }

bool valid = false;
error = signal_aes256_gcm_decryption_verify_tag(&valid, decrypt, tag); // VERY IMPORTANT
if (error || !valid) { return NULL; }

error = signal_aes256_gcm_decryption_destroy(decrypt);
if (error) { /* log, maybe? */ }

char *result = malloc(message.length);
memcpy(result, message.buffer, message.length);
return result;

I'll note that this is a relatively "unsafe" implementation of AES-GCM, because it requires you to remember to call verify_tag at the end. If the tag doesn't verify, the decrypted message must be thrown away. A more common API would have you decrypt-and-verify as a single operation to be safe, but that requires the whole message be in memory at once.

@JuyeonYu
Copy link
Author

JuyeonYu commented Jul 1, 2022

thank you for your reply!
I couldn't fully understand what you said. :(

Q1. in Swift, is "Aes256GcmSiv class" the higher-level operations for that?
so can I decrypt without tag verify in safe?

and from your sample code I made the below code in Swift.
but I don't know how can I make "SignalAes256GcmDecryption *decrypt;"(from your sample) in Swift.

Q2. how can I make decrypt variable below code?
and... is that right approach?

var messageKey: [UInt8] = messageKeyHex.data(using: .utf8)?.bytes
var tag: [UInt8] = tagHex.data(using: .utf8)?.bytes
var nonce: [UInt8] =  nonceHex.data(using: .utf8)?.bytes
var aead: [UInt8] = aeadHex.data(using: .utf8)?.bytes
var cypher: [UInt8] = cypherHex.data(using: .utf8)?.bytes

withUnsafePointer(to: messageKey[0]) { messageKeyPointer in
  withUnsafePointer(to: tag[0]) { tagPointer in
    withUnsafePointer(to: nonce[0]) { noncePointer in
      withUnsafePointer(to: aead[0]) { aeadPointer in
        withUnsafeMutablePointer(to: &myCypher[0]) { cypherPointer in
          let messageKeyBuffer = SignalBorrowedBuffer(base: messageKeyPointer, length: UInt(messageKey.count))
          let tagBuffer = SignalBorrowedBuffer(base: tagPointer, length: UInt(tag.count))
          let nonceBuffer = SignalBorrowedBuffer(base: noncePointer, length: UInt(nonce.count))
          let aeadBuffer = SignalBorrowedBuffer(base: aeadPointer, length: UInt(aead.count))
          let cypherBuffer = SignalBorrowedMutableBuffer(base: cypherPointer, length: UInt(cypher.count))

          // how to make the ??? arguement below?
          var error = signal_aes256_gcm_decryption_new(???, messageKeyBuffer, nonceBuffer, aeadBuffer)
          if error != nil { }
          
          // how to make the ??? arguement below?      
          error = signal_aes256_gcm_decryption_update(???, cypherBuffer, 0, UInt32(cypher.count))
          if error != nil { }
                        
          // how to make the ??? arguement below?
          var valid: Bool = false
          error = signal_aes256_gcm_decryption_verify_tag(&valid, ???, tagBuffer)
          if error != nil { }
        }
      }
   }
}

}

thank you again for your reply!

@JuyeonYu JuyeonYu closed this as completed Jul 5, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

2 participants