aidantwoods / swift-paseto

Platform-Agnostic Security Tokens implementation in Swift
MIT License
22 stars 5 forks source link

CocoaPods support #5

Open davidperrenoud opened 5 years ago

davidperrenoud commented 5 years ago

Have you already tried supporting CocoaPods?

As far as I have tested, the only complicated point is the direct dependency on Clibsodium which is needed for 2 functions: crypto_aead_xchacha20poly1305_ietf_encrypt and crypto_aead_xchacha20poly1305_ietf_decrypt.

Is there a reason why the Aead extensions from Swift-Sodium could not be used in place of these 2 functions?

davidperrenoud commented 5 years ago

Related issue: https://github.com/jedisct1/swift-sodium/pull/173

davidperrenoud commented 5 years ago

@aidantwoods Do you have any thought about this?

It looks like specifying nonces when performing AEAD has been made optional in draft-paragon-paseto-rfc-01 which would allow to drop the Clibsodium dependency, though I do not know when this version of the RFC will be online or official.

aidantwoods commented 5 years ago

Apologies for letting this linger a little.

I think your assessment in https://github.com/aidantwoods/swift-paseto/commit/517624c6374f5c0d070998d74588e5762688c53c#commitcomment-31681166 is correct: I had actually missed that the RFC text changed to make this optional, so yes I think we could drop Clibsodium as a direct dependency while still technically following the spec (and dropping PASETO's way of guarding against an RNG failure would seem to be fine, given precautions already taken by libsodium: https://github.com/jedisct1/swift-sodium/pull/173#issuecomment-447327677).

I also would prefer not to depend on Clibsodium directly anyway (orthogonally to this issue RE CocoaPods), since it isn't exactly ideal to be interacting directly with C code if it can be avoided—that's swift-sodium's job.

One thing dropping Clibsodium (and thus also being able to choose a nonce) may complicate, though, is unit testing. The unit tests currently use @testable import Paseto which exposes an internal part of the API, which permits specifying a nonce for the purpose of unit testing against the PASETO test vectors. But there would be no way to encrypt deterministically using just swift-sodium's AEAD interface.

aidantwoods commented 5 years ago

So I'm just taking another look at this. Issues with unit testing aside, there's actually a blocking issue: the PASETO spec essentially requires deterministic encryption to be available via the necessity that the nonce that will be used for encryption is known prior to providing the additional data (used to calculate the value returned by Util.pae): https://github.com/aidantwoods/swift-paseto/blob/517624c6374f5c0d070998d74588e5762688c53c/Sources/Paseto/Implementations/Version2/V2Local.swift#L36-L41

This obviously means that (using what's available in the swift-sodium API), something like

let (cipherText, nonce) = sodium.aead.xchacha20poly1305ietf.encrypt(
    message: message,
    secretKey: key.material,
    additionalData: ...
)

isn't going to work: since we can't yet calculate the value for the additionalData parameter until the call returns. I don't think there's really a good way around this in the swift-sodium API either, without introducing a possibility for nonce reuse.

davidperrenoud commented 5 years ago

@aidantwoods You don't need the nonce, you can use random bytes as defined in paseto-rfc-01:

   2.  Generate 24 random bytes from the OS's CSPRNG.

   3.  Optionally, calculate [...] This will be our nonce, "n".

       *  If this step is omitted, the output of step 2 is "n" instead.

   4.  Pack "h", "n", and "f" together (in that order) using PAE (see
       Section 2.2).  We'll call this "preAuth".

The confusing part is "If this step is omitted, the output of step 2 is "n" instead." This simply means that "n" is a nonce, not the nonce used to encrypt the payload.

@paragonie Could you rewrite steps 2-3 and merge these two options together to make this more obvious?

aidantwoods commented 5 years ago

This still won't work because I need to use the same random bytes for the value of n in calculating preAuth. But I don't know which random bytes Swift-sodium will pick (and need them prior to encrypting for providing the correct the additional data value). If I just use random bytes that don't match the nonce libsodium assigns then decryption would fail.

davidperrenoud commented 5 years ago

Could you open an issue on PASETO's repository? You might be able to better describe the problem than me.

aidantwoods commented 5 years ago

Thanks for opening that—I'm not entirely sure if the revised wording in draft-paragon-paseto-rfc-01 had the intent of accommodating this particular use case, so that issue should hopefully clarify things.

aidantwoods commented 4 years ago

Oops, I didn't mean to let this sit for so long.

I think we should presume that the spec won't change to accommodate using non-deterministic aead variants. I noticed you added a .podspec in your fork, did you manage to get something working that still incorporates Clibsodium?