/// <summary> /// Set up the ChaCha state with the given key. A 32-byte key is required /// and enforced. /// </summary> /// <param name="key"> /// A 32-byte (256-bit) key, treated as a concatenation of eight 32-bit /// little-endian integers /// </param> private void KeySetup(byte[] key) { if (key == null) { throw new ArgumentNullException("Key is null"); } if (key.Length != 32) { throw new ArgumentException("Key length must be 32. Actual is " + key.Length.ToString()); } // These are the same constants defined in the reference implementation // see http://cr.yp.to/streamciphers/timings/estreambench/submissions/salsa20/chacha8/ref/chacha.c int keyIndex = key.Length - 16; fixed(uint *state = ctx.state) fixed(byte *k = key) { state[0] = Chacha.Constants[0]; state[1] = Chacha.Constants[1]; state[2] = Chacha.Constants[2]; state[3] = Chacha.Constants[3]; state[4] = Chacha.U8To32Little(k, 0); state[5] = Chacha.U8To32Little(k, 4); state[6] = Chacha.U8To32Little(k, 8); state[7] = Chacha.U8To32Little(k, 12); state[8] = Chacha.U8To32Little(k, 16); state[9] = Chacha.U8To32Little(k, 20); state[10] = Chacha.U8To32Little(k, 24); state[11] = Chacha.U8To32Little(k, 28); } }
/// <summary> /// Set up the ChaCha state with the given nonce (aka Initialization Vector /// or IV) and block counter. A 12-byte nonce and a 4-byte counter are /// required and enforced. /// </summary> /// <param name="nonce"> /// A 12-byte (96-bit) nonce, treated as a concatenation of three 32-bit /// little-endian integers /// </param> /// <param name="counter"> /// A 4-byte (32-bit) block counter, treated as a 32-bit little-endian integer /// </param> public void IVSetup(byte[] nonce, uint counter) { if (nonce == null) { throw new ArgumentNullException("Nonce is null"); } if (nonce.Length != 12) { throw new ArgumentException( "Nonce length should be 12. Actual is " + nonce.Length.ToString() ); } _iv = nonce; fixed(byte *n = nonce) { ctx.state[12] = counter; ctx.state[13] = Chacha.U8To32Little(n, 0); ctx.state[14] = Chacha.U8To32Little(n, 4); ctx.state[15] = Chacha.U8To32Little(n, 8); } }
private static void NextKeystreamBuffer(Context *ctx) { Chacha.ChachaBlockFunction(ctx->state, (uint *)ctx->keyStreamBuffer, 20 / 2); ctx->state[12]++; }