private static byte[] XChaCha20Poly1305(bool isEncryption, byte[] key, byte[] nonce, byte[] message, byte[] aad = null)
        {
            if (key.Length != 32)
            {
                throw new ArgumentException("Key must be 32 bytes", nameof(key));
            }
            if (nonce.Length != 24)
            {
                throw new ArgumentException("Nonce must be 24 bytes", nameof(nonce));
            }

            // subkey (hchacha20(key, nonce[0:15]))
            var subkey = HChaCha20.CreateSubkey(key, nonce); // TODO: parse nonce bytes to pass through here instead

            // nonce (chacha20_nonce = "\x00\x00\x00\x00" + nonce[16:23])
            var chaChaNonce = new byte[12];

            Array.Copy(new byte[] { 0, 0, 0, 0 }, chaChaNonce, 4);
            Array.Copy(nonce, 16, chaChaNonce, 4, 8);

            // chacha20_encrypt(subkey, chacha20_nonce, plaintext, blk_ctr)
            var outputLength = message.Length;

            if (isEncryption)
            {
                outputLength += 16;
            }
            else
            {
                outputLength -= 16;
            }

            var output      = new byte[outputLength];
            var keyMaterial = new KeyParameter(subkey);
            var parameters  = new ParametersWithIV(keyMaterial, chaChaNonce);

            var chaCha20Poly1305 = new ChaCha20Poly1305();

            chaCha20Poly1305.Init(isEncryption, parameters);

            // if aditional data present
            if (aad != null)
            {
                chaCha20Poly1305.ProcessAadBytes(aad, 0, aad.Length);
            }

            var len = chaCha20Poly1305.ProcessBytes(message, 0, message.Length, output, 0);

            chaCha20Poly1305.DoFinal(output, len);

            return(output);
        }
Example #2
0
        public static byte[] Encode(byte[] input, byte[] key, byte[] nonce)
        {
            var subNonce = new byte[12];

            if (nonce.Length == 24)
            {
                var hNonce = new byte[16];
                System.Buffer.BlockCopy(nonce, 0, hNonce, 0, 16);
                System.Buffer.BlockCopy(nonce, 16, subNonce, 4, 8);
                key = HChaCha20.Encode(key, hNonce);
            }
            else if (nonce.Length == 12)
            {
                System.Buffer.BlockCopy(nonce, 0, subNonce, 0, 12);
            }
            else
            {
                throw new System.ArgumentException();
            }

            return(NormalEncode(input, key, subNonce));
        }