Mercurial > hg > ucis.core
diff NaCl/crypto_stream/salsa20.cs @ 20:c873e3dd73fe
Added NaCl cryptography code
author | Ivo Smits <Ivo@UCIS.nl> |
---|---|
date | Mon, 15 Apr 2013 00:43:48 +0200 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/NaCl/crypto_stream/salsa20.cs Mon Apr 15 00:43:48 2013 +0200 @@ -0,0 +1,123 @@ +using System; + +namespace UCIS.NaCl.crypto_stream { + static unsafe class salsa20 { + public const int KEYBYTES = 32; + public const int NONCEBYTES = 8; + + static Byte[] sigma = new Byte[16] {(Byte)'e', (Byte)'x', (Byte)'p', (Byte)'a', //[16] = "expand 32-byte k"; + (Byte)'n', (Byte)'d', (Byte)' ', (Byte)'3', + (Byte)'2', (Byte)'-', (Byte)'b', (Byte)'y', + (Byte)'t', (Byte)'e', (Byte)' ', (Byte)'k', }; + + public static void crypto_stream(Byte* c, int clen, Byte* n, Byte* k) { + Byte[] inv = new Byte[16]; + Byte[] block = new Byte[64]; + if (clen == 0) return; + + for (int i = 0; i < 8; ++i) inv[i] = n[i]; + for (int i = 8; i < 16; ++i) inv[i] = 0; + + while (clen >= 64) { + fixed (Byte* invp = inv, sigmap = sigma) crypto_core.salsa20.crypto_core(c, invp, k, sigmap); + + UInt32 u = 1; + for (int i = 8; i < 16; ++i) { + u += inv[i]; + inv[i] = (Byte)u; + u >>= 8; + } + + clen -= 64; + c += 64; + } + + if (clen != 0) { + fixed (Byte* invp = inv, sigmap = sigma, blockp = block) crypto_core.salsa20.crypto_core(blockp, invp, k, sigmap); + for (int i = 0; i < clen; ++i) c[i] = block[i]; + } + } + + public static void crypto_stream_xor(Byte* c, Byte* m, int mlen, Byte* n, Byte* k) { + Byte[] inv = new Byte[16]; + Byte[] block = new Byte[64]; + if (mlen == 0) return; + + for (int i = 0; i < 8; ++i) inv[i] = n[i]; + for (int i = 8; i < 16; ++i) inv[i] = 0; + + while (mlen >= 64) { + fixed (Byte* invp = inv, sigmap = sigma, blockp = block) crypto_core.salsa20.crypto_core(blockp, invp, k, sigmap); + for (int i = 0; i < 64; ++i) c[i] = (Byte)(m[i] ^ block[i]); + + UInt32 u = 1; + for (int i = 8; i < 16; ++i) { + u += inv[i]; + inv[i] = (Byte)u; + u >>= 8; + } + + mlen -= 64; + c += 64; + m += 64; + } + + if (mlen != 0) { + fixed (Byte* invp = inv, sigmap = sigma, blockp = block) crypto_core.salsa20.crypto_core(blockp, invp, k, sigmap); + for (int i = 0; i < mlen; ++i) c[i] = (Byte)(m[i] ^ block[i]); + } + } + + internal static void crypto_stream_xor_split(Byte* mcpad, int padbytes, Byte* c, Byte* m, int mlen, Byte* n, Byte* k) { + Byte* inv = stackalloc Byte[16]; + Byte* block = stackalloc Byte[64]; + + for (int i = 0; i < 8; ++i) inv[i] = n[i]; + for (int i = 8; i < 16; ++i) inv[i] = 0; + + if (padbytes > 0) { + if (padbytes > 64) throw new ArgumentOutOfRangeException("padbytes"); + crypto_core.salsa20.crypto_core(block, inv, k, sigma); + if (mcpad != null) for (int i = 0; i < padbytes; ++i) mcpad[i] ^= block[i]; + if (mlen > 0) { + int bleft = 64 - padbytes; + if (bleft > mlen) bleft = mlen; + for (int i = 0; i < bleft; ++i) c[i] = (Byte)(m[i] ^ block[i + padbytes]); + c += bleft; + m += bleft; + mlen -= bleft; + if (mlen >= 0) { + UInt32 u = 1; + for (int i = 8; i < 16; ++i) { + u += inv[i]; + inv[i] = (Byte)u; + u >>= 8; + } + } + } + } + + while (mlen >= 64) { + crypto_core.salsa20.crypto_core(block, inv, k, sigma); + //for (int i = 0; i < 64; ++i) c[i] = (Byte)(m[i] ^ block[i]); + for (int i = 0; i < 64; i += 4) *(int*)(c + i) = *(int*)(m + i) ^ *(int*)(block + i); + + UInt32 u = 1; + for (int i = 8; i < 16; ++i) { + u += inv[i]; + inv[i] = (Byte)u; + u >>= 8; + } + + mlen -= 64; + c += 64; + m += 64; + } + + if (mlen > 0) { + crypto_core.salsa20.crypto_core(block, inv, k, sigma); + for (int i = 0; i < mlen; ++i) c[i] = (Byte)(m[i] ^ block[i]); + } + } + } +} \ No newline at end of file