DCIT / perl-CryptX

https://metacpan.org/pod/CryptX
Other
35 stars 23 forks source link

missing AEAD_CHACHA20_POLY1305 [RFC7539] support #35

Closed zhou0 closed 7 years ago

zhou0 commented 7 years ago

I find chacha20 and poly1305 related code in this project but there is no AuthEnc package for that.

Currently, only https://metacpan.org/release/Crypt-NaCl-Sodium supports AEAD_CHACHA20_POLY1305 but this module does not build on Windows .

http://code.activestate.com/ppm/Crypt-NaCl-Sodium/

karel-m commented 7 years ago

Try development version https://metacpan.org/release/MIK/CryptX-0.047_003

https://metacpan.org/pod/release/MIK/CryptX-0.047_003/lib/Crypt/AuthEnc/ChaCha20Poly1305.pm

zhou0 commented 7 years ago

a convenience function which increment a nonce is also needed, such as

https://metacpan.org/pod/distribution/Crypt-NaCl-Sodium/lib/Data/BytesLocker.pod#increment

karel-m commented 7 years ago

a convenience function which increment a nonce is also needed, such as

What is the use case?

I am not sure whether Data::BytesLocker is comparable to Crypt::AuthEnc::ChaCha20Poly1305.

zhou0 commented 7 years ago

the IV in aead-chacha20-poly1305 is usually a 96 bits nonce that starts from zero and increment by 1 after every aead operation. This is different with other IV use case where it can be created by calling random_bytes(). Without a nonce increment function, user has no easy easy to supply the nonce for aead-chacha20-poly1305.

for your reference, line 832 to line 842 of this c code is a nonce increment function that i write.

https://github.com/zhou0/mysocks/blob/master/src/cipher-wolfssl.c

line 570 to 581 is libsodium's implementation

https://github.com/jedisct1/libsodium/blob/1.0.4/src/libsodium/sodium/utils.c

karel-m commented 7 years ago

In libtomcrypt we have something like:

int chacha20poly1305_setiv_rfc7905(chacha20poly1305_state *st, 
                                   const unsigned char *iv, unsigned long ivlen, 
                                   ulong64 sequence_number)
{
   int i;
   unsigned char combined_iv[12] = { 0 };

   LTC_ARGCHK(st != NULL);
   LTC_ARGCHK(iv != NULL);
   LTC_ARGCHK(ivlen == 12);

   STORE64L(sequence_number, combined_iv + 4);
   for (i = 0; i < 12; i++) combined_iv[i] = iv[i] ^ combined_iv[i];
   return chacha20poly1305_setiv(st, combined_iv, 12);
}

It follows https://tools.ietf.org/html/rfc7905#section-2

I can quite easily make it available from perl but I am not sure if it is what you want.

zhou0 commented 7 years ago

This is another way of generating nonces, by combing a fixed sequence number and a randomly generated IV . This should be a must have.

What i need does not involve TLS. It is defined in the shadowsocks protocol. https://shadowsocks.org/en/spec/AEAD-Ciphers.html whichs states:

The first AEAD encrypt/decrypt operation uses a counting nonce starting from 0. After each encrypt/decrypt operation, the nonce is incremented by one as if it were an unsigned little-endian integer. Note that each TCP chunk involves two AEAD encrypt/decrypt operation: one for the payload length, and one for the payload. Therefore each chunk increases the nonce twice.

AEAD is not just been used in TLS now. OpenSSH and OpenVPN all have different ways on how nonces are set up, not necessarily in identical ways of TLS but still compliant with standard which only requires that nonce is 96 bits and non-repeating . Shadowocks is just another example.

karel-m commented 7 years ago

OK we have 96bits of nonce (12 bytes) + 32bits of counter (4 bytes).

I understand that you need to increment nounce part but what to do with the counter part? leave it as it is? reset it to 1?

zhou0 commented 7 years ago

thee is an internal counter in chacha20 , and you can set this counter. it is an interger in C. incrementing it is just like incrementing an interger. so there is no special need for an increment function for it.

in chacha20-poly1305, the internal counter is till there i think, but this internal counter is not exposed to the caller interface. There is no api to set that counter. instead we set the IV(Nonce ). and since thee is no existing C data types that is 12 bytes. a special increment function is needed to increment that nonce.

a nonce is incremented so that client dont have to send that nonce to server, server dont have to send that nonce to client either. if a randomly generated nonce is used, client and server must have some way to shared that nonce. so incrementing nonces makes sharing nonces unnecessary, The goal of combing nones achieves the same goal.

karel-m commented 7 years ago

Untested attempt added to CryptX-0.047_004

See increment_iv method in https://metacpan.org/pod/release/MIK/CryptX-0.047_004/lib/Crypt/AuthEnc/ChaCha20Poly1305.pm

zhou0 commented 7 years ago

I tested the chacha20 stream cipher and it works.

could you decouple the nonce function with chacha20-poly1305 and make it a generic helper package? currently i am using the nonce increment package from Crypt::Nacl::Sodium to manipulate nonce and Crypt::AuthEnc::GCM to implement AEAD with AES. With your chacha20poly1305 package, i can manipulate the nonce without Crypt::Nacl::Sodium when using chacha20 AEAD, but AEAD with AES still need Crypt::Nacl::Sodium to increment nonces.

karel-m commented 7 years ago

Well, I can try to add something like this simple function:

use Crypt::Misc 'increment_octets_le';

my $nonce = pack("H*", "1F1F1F1F1F1F");
# do something with $nonce
$nonce = increment_octets_le($nonce);
# do something else with incremented $nonce

Would it be sufficient?

zhou0 commented 7 years ago

in Crypt::Nacl::Sodium , there are 3 functions: nonce ( for 64 bits ) and ietf_nonce ( for 96 bits ) and aes256gcm_nonce ( also 96 bits ), see

https://metacpan.org/pod/distribution/Crypt-NaCl-Sodium/lib/Crypt/NaCl/Sodium/aead.pod

actually we need just one constructor function with a length argument ( either 8 or 12 ). and one increment function . I would put it in Crypt::AuthEnc, the parent package of all AEAD packages.

karel-m commented 7 years ago

in CryptX-0.047_005 I have added increment_octets_be + increment_octets_le (both just functions available in Crypt::Misc) which works like this:

use Crypt::Misc qw(increment_octets_be increment_octets_le);
use Crypt::PRNG qw(random_bytes);

my $nonce = random_bytes(3);
for (1..9999) {
  $nonce = increment_octets_le($nonce);
  printf "$_: " . unpack("H*", $nonce) . "\n";
}

ChaCha20Poly1305's increment_iv was removed.

karel-m commented 7 years ago

CryptX-0.047_005 was broken, please try CryptX-0.047_006

zhou0 commented 7 years ago

it seems that the chacha20poly1305_decrypt_verify function in 0.047_006 is not working.

karel-m commented 7 years ago

I have not changed chacha20poly1305_decrypt_verify in 0.047_006 (at least not intentionally). Do you have some failing example?

karel-m commented 7 years ago

could you please check CryptX-0.048_002, if there is no feedback I am going to close this issue with coming 0.049 release

karel-m commented 7 years ago

0.049 released

zhou0 commented 7 years ago

sorry, i was busy preparing for an exam. I will be back after middle september.