diff --git a/src/Home/Crypto/AES128/AES128.ZC b/src/Home/Crypto/AES128/AES128.ZC new file mode 100644 index 00000000..4b965b1d --- /dev/null +++ b/src/Home/Crypto/AES128/AES128.ZC @@ -0,0 +1,331 @@ +#define Nb 4 // The number of columns comprising a state in AES. This is a constant in AES. Value=4 +#define Nk 4 // The number of 32 bit words in a key. +#define Nr 10 // amount of rounds to expand the key + +// could be calculated on the fly too... i guess +// https://en.wikipedia.org/wiki/Rijndael_S-box +U8 sBox[256] = { + //0 1 2 3 4 5 6 7 8 9 A B C D E F + 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, + 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, + 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, + 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, + 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, + 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, + 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, + 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, + 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, + 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, + 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, + 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, + 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, + 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, + 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, + 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 +}; + +// U8 reverse_sBox[256] = { +// 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, +// 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, +// 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, +// 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, +// 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, +// 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, +// 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, +// 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, +// 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, +// 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e, +// 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, +// 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, +// 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f, +// 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, +// 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, +// 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d +// }; + +U8 Rcon[255] = { + 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, + 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, + 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, + 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, + 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, + 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, + 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, + 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, + 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, + 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, + 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, + 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, + 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, + 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, + 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, + 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb +}; + +// Mul2 and Mul3 could be precomputed, but here's a simple implementation +// Note: This is a simplified and not optimized version +U8 xtime(U8 x) { + return (x << 1) ^ (((x >> 7) & 1) * 0x1b); +} + +U8 Mul2[256], Mul3[256]; + +U0 InitMulTables() { + I64 i; + for (i = 0; i < 256; i++) { + Mul2[i] = xtime(i); + Mul3[i] = xtime(i) ^ i; + } +} + +U0 KeyExpansion(U8 *RoundKey, U8 *Key) { + I64 i, j, k; + U8 tempa[4]; // Temporary storage array + + // Copy the original key to the first round key + for (i = 0; i < Nk; ++i) { + RoundKey[(i * 4) + 0] = Key[(i * 4) + 0]; + RoundKey[(i * 4) + 1] = Key[(i * 4) + 1]; + RoundKey[(i * 4) + 2] = Key[(i * 4) + 2]; + RoundKey[(i * 4) + 3] = Key[(i * 4) + 3]; + } + + // Expand the keys for the remaining rounds + for (i = Nk; i < Nb * (Nr + 1); ++i) { + // Fetch the previous word + k = (i - 1) * 4; + tempa[0] = RoundKey[k + 0]; + tempa[1] = RoundKey[k + 1]; + tempa[2] = RoundKey[k + 2]; + tempa[3] = RoundKey[k + 3]; + + if (i % Nk == 0) { + // Rotate the word and apply S-box substitution + U8 u8tmp = tempa[0]; + tempa[0] = sBox[tempa[1]]; + tempa[1] = sBox[tempa[2]]; + tempa[2] = sBox[tempa[3]]; + tempa[3] = sBox[u8tmp]; + + // XOR with Rcon[i/Nk] + tempa[0] = tempa[0] ^ Rcon[i / Nk]; + } + + // XOR tempa with the word Nk positions before + j = i * 4; k = (i - Nk) * 4; + RoundKey[j + 0] = RoundKey[k + 0] ^ tempa[0]; + RoundKey[j + 1] = RoundKey[k + 1] ^ tempa[1]; + RoundKey[j + 2] = RoundKey[k + 2] ^ tempa[2]; + RoundKey[j + 3] = RoundKey[k + 3] ^ tempa[3]; + } +} + +U0 AddRoundKey(U8 round, U8 *state, U8 *RoundKey) { + I64 i, j; + for (i = 0; i < 4; i++) { + for (j = 0; j < 4; j++) { + state[j * 4 + i] ^= RoundKey[round * Nb * 4 + i * Nb + j]; + } + } +} + +U0 SubBytes(U8 *state) { + I64 i; + for (i = 0; i < 16; i++) { + state[i] = sBox[state[i]]; + } +} + +U0 ShiftRows(U8 *state) { + U8 temp; + + // Shift the second row (1 shift to the left) + temp = state[1]; + state[1] = state[5]; + state[5] = state[9]; + state[9] = state[13]; + state[13] = temp; + + // Shift the third row (2 shifts to the left) + temp = state[2]; + state[2] = state[10]; + state[10] = temp; + temp = state[6]; + state[6] = state[14]; + state[14] = temp; + + // Shift the fourth row (3 shifts to the left) + temp = state[3]; + state[3] = state[15]; + state[15] = state[11]; + state[11] = state[7]; + state[7] = temp; +} + +U0 MixColumns(U8 *state) { + for (I64 i = 0; i < 4; ++i) { + U8 a0 = state[i * 4 + 0]; + U8 a1 = state[i * 4 + 1]; + U8 a2 = state[i * 4 + 2]; + U8 a3 = state[i * 4 + 3]; + + U8 r0 = Mul2[a0] ^ Mul3[a1] ^ a2 ^ a3; + U8 r1 = a0 ^ Mul2[a1] ^ Mul3[a2] ^ a3; + U8 r2 = a0 ^ a1 ^ Mul2[a2] ^ Mul3[a3]; + U8 r3 = Mul3[a0] ^ a1 ^ a2 ^ Mul2[a3]; + + state[i * 4 + 0] = r0; + state[i * 4 + 1] = r1; + state[i * 4 + 2] = r2; + state[i * 4 + 3] = r3; + } +} + +// U0 InvSubBytes(U8 *state) { +// // Implement inverse of SubBytes +// } + +// U0 InvShiftRows(U8 *state) { +// // Implement inverse of ShiftRows +// } + +// U0 InvMixColumns(U8 *state) { +// // Implement inverse of MixColumns +// } + +// U0 InvCipher(U8 *state, U8 *RoundKey) { +// I64 round; +// // Start by adding the last round key +// AddRoundKey(Nr, state, RoundKey); + +// // Perform the rounds in reverse order +// for (round = Nr - 1; round > 0; round--) { +// InvShiftRows(state); +// InvSubBytes(state); +// AddRoundKey(round, state, RoundKey); +// InvMixColumns(state); +// } + +// // Final round (without MixColumns) +// InvShiftRows(state); +// InvSubBytes(state); +// AddRoundKey(0, state, RoundKey); +// } + +U0 Cipher(U8 *state, U8 *RoundKey) { + I64 round; + // Add the First round key to the state before starting the rounds + AddRoundKey(0, state, RoundKey); + + // There will be Nr rounds + for (round = 1; round < Nr; ++round) { + SubBytes(state); + ShiftRows(state); + MixColumns(state); + AddRoundKey(round, state, RoundKey); + } + + // The last round is given below + SubBytes(state); + ShiftRows(state); + AddRoundKey(Nr, state, RoundKey); +} + +U0 AES_init_ctx(U8 *ctx, U8 *key) { + KeyExpansion(ctx, key); +} + +U0 AES_ECB_encrypt(U8 *ctx, U8 *buf) { + // Buffer size is assumed to be multiple of 16 bytes! (AES block size) + Cipher(buf, ctx); +} + +// U0 AES_ECB_decrypt(U8 *ctx, U8 *buf) { +// InvCipher(buf, ctx); +// } + +U0 PrintHex(U8 *buf, I64 len) { + I64 i; + for (i = 0; i < len; i++) "%02X ", buf[i]; + "\n"; +} + +U8 HexCharToByte(U8 ch) { + if (ch >= '0' && ch <= '9') return ch - '0'; + if (ch >= 'a' && ch <= 'f') return 10 + ch - 'a'; + if (ch >= 'A' && ch <= 'F') return 10 + ch - 'A'; + return 0; // Non-hex character +} + +U0 HexStringToByteArray(U8 *hexString, U8 *byteArray, I64 byteArrayLength) { + I64 i; + for (i = 0; i < byteArrayLength; i++) { + byteArray[i] = HexCharToByte(hexString[2 * i]) << 4 | HexCharToByte(hexString[2 * i + 1]); + } +} + +// 9d3492551250741cef1bf7892fabd07b +U8 key[16] = {0x9d, 0x34, 0x92, 0x55, 0x12, 0x50, 0x74, 0x1c, 0xef, 0x1b, 0xf7, 0x89, 0x2f, 0xab, 0xd0, 0x7b}; +// 0c40d19e21ac91fad03b1a8e5349f245 +U8 buf[16] = {0x0c, 0x40, 0xd1, 0x9e, 0x21, 0xac, 0x91, 0xfa, 0xd0, 0x3b, 0x1a, 0x8e, 0x53, 0x49, 0xf2, 0x45}; + +U0 Main() { + U8 ctx[176]; // Context (expanded key) + + InitMulTables(); + AES_init_ctx(ctx, key); + AES_ECB_encrypt(ctx, buf); + + // `buf` now contains the ciphertext + "Result:\n$$LTRED$$"; + PrintHex(buf, 16); + "\n$$FG$$"; +} + +Main; + + +// U0 Main() { + +// U8 ctx[176]; // Context (expanded key) + +// InitMulTables; + +// AES_init_ctx(ctx, key); + +// "ctx:\n"; +// PrintHex(ctx, 176); +// "\n"; + +// AES_ECB_encrypt(ctx, buf); +// "buf:\n$$LTGREEN$$"; +// PrintHex(buf, 16); +// "\n$$FG$$"; +// } +// Main; + +// // 9d3492551250741cef1bf7892fabd07b +// U8 key[16] = {0x9d, 0x34, 0x92, 0x55, 0x12, 0x50, 0x74, 0x1c, 0xef, 0x1b, 0xf7, 0x89, 0x2f, 0xab, 0xd0, 0x7b}; +// // 0c40d19e21ac91fad03b1a8e5349f245 +// U8 buf[16] = {0x0c, 0x40, 0xd1, 0x9e, 0x21, 0xac, 0x91, 0xfa, 0xd0, 0x3b, 0x1a, 0x8e, 0x53, 0x49, 0xf2, 0x45}; + +// U0 Main(U8 *keyHexString, U8 *plaintextHexString) { + +// U8 ctx[176]; // Context (expanded key) + +// InitMulTables(); + +// // Convert hex string to byte array for the key +// HexStringToByteArray(keyHexString, key, 16); + +// // Convert hex string to byte array for the plaintext +// HexStringToByteArray(plaintextHexString, buf, 16); + +// AES_init_ctx(ctx, key); +// AES_ECB_encrypt(ctx, buf); + +// // `buf` now contains the ciphertext +// PrintHex(buf, 16); +// } + +// // Main("9d3492551250741cef1bf7892fabd07b", "0c40d19e21ac91fad03b1a8e5349f245"); \ No newline at end of file diff --git a/src/Home/Crypto/ChaCha20/ChaCha20.ZC b/src/Home/Crypto/ChaCha20/ChaCha20.ZC new file mode 100644 index 00000000..0aef429f --- /dev/null +++ b/src/Home/Crypto/ChaCha20/ChaCha20.ZC @@ -0,0 +1,181 @@ + +// Rotating bits left +U32 RotL32(U32 x, I32 n) { + return (x << n) | (x >> (32 - n)); +} + +// Packing bytes into a 32-bit unsigned integer +U32 Pack4(U8 *a) { + U32 res = 0; + res |= a[0](U32) << 0 * 8; + res |= a[1](U32) << 1 * 8; + res |= a[2](U32) << 2 * 8; + res |= a[3](U32) << 3 * 8; + return res; +} + +// Unpacking a 32-bit unsigned integer into bytes +U0 UnPack4(U32 src, U8 *dst) { + dst[0] = (src >> 0 * 8) & 0xff; + dst[1] = (src >> 1 * 8) & 0xff; + dst[2] = (src >> 2 * 8) & 0xff; + dst[3] = (src >> 3 * 8) & 0xff; +} + +// ChaCha20 context structure +class chacha20_context { + U32 state[16]; + U32 keystream32[16]; + U8 key[32]; + U8 nonce[12]; + U64 counter; + U32 position; +}; + +U8 *magic_constant = "expand 32-byte k"; +// Initializing the ChaCha20 block +U0 chacha20_init_block(chacha20_context *ctx, U8 *key, U8 *nonce) { + MemCopy(ctx->key, key, 32); + MemCopy(ctx->nonce, nonce, 12); + + ctx->state[0] = Pack4(magic_constant + 0 * 4); + ctx->state[1] = Pack4(magic_constant + 1 * 4); + ctx->state[2] = Pack4(magic_constant + 2 * 4); + ctx->state[3] = Pack4(magic_constant + 3 * 4); + ctx->state[4] = Pack4(key + 0 * 4); + ctx->state[5] = Pack4(key + 1 * 4); + ctx->state[6] = Pack4(key + 2 * 4); + ctx->state[7] = Pack4(key + 3 * 4); + ctx->state[8] = Pack4(key + 4 * 4); + ctx->state[9] = Pack4(key + 5 * 4); + ctx->state[10] = Pack4(key + 6 * 4); + ctx->state[11] = Pack4(key + 7 * 4); + // 64 bit counter initialized to zero by default. + ctx->state[12] = 0; + ctx->state[13] = Pack4(nonce + 0 * 4); + ctx->state[14] = Pack4(nonce + 1 * 4); + ctx->state[15] = Pack4(nonce + 2 * 4); + + MemCopy(ctx->nonce, nonce, 12); +} + +// Setting the counter for the ChaCha20 block +U0 chacha20_block_set_counter(chacha20_context *ctx, U64 counter) { + ctx->state[12] = counter(U32); + ctx->state[13] = Pack4(ctx->nonce + 0 * 4) + (counter >> 32)(U32); +} + +U0 CHACHA20_QUARTERROUND(U32 *x, I32 a, I32 b, I32 c, I32 d) { + x[a] += x[b]; x[d] = RotL32(x[d] ^ x[a], 16); + x[c] += x[d]; x[b] = RotL32(x[b] ^ x[c], 12); + x[a] += x[b]; x[d] = RotL32(x[d] ^ x[a], 8); + x[c] += x[d]; x[b] = RotL32(x[b] ^ x[c], 7); +} + +// Generating the next ChaCha20 block +U0 chacha20_block_next(chacha20_context *ctx) { + I32 i; + for (i = 0; i < 16; i++) ctx->keystream32[i] = ctx->state[i]; + + for (i = 0; i < 10; i++) { + CHACHA20_QUARTERROUND(ctx->keystream32, 0, 4, 8, 12); + CHACHA20_QUARTERROUND(ctx->keystream32, 1, 5, 9, 13); + CHACHA20_QUARTERROUND(ctx->keystream32, 2, 6, 10, 14); + CHACHA20_QUARTERROUND(ctx->keystream32, 3, 7, 11, 15); + CHACHA20_QUARTERROUND(ctx->keystream32, 0, 5, 10, 15); + CHACHA20_QUARTERROUND(ctx->keystream32, 1, 6, 11, 12); + CHACHA20_QUARTERROUND(ctx->keystream32, 2, 7, 8, 13); + CHACHA20_QUARTERROUND(ctx->keystream32, 3, 4, 9, 14); + } + for (i = 0; i < 16; i++) ctx->keystream32[i] += ctx->state[i]; + + U32 *counter = ctx->state + 12; + counter[0]++; + if (counter[0] == 0) { + counter[1]++; + if (counter[1] == 0) { + // Handle the counter overflow, e.g., print an error message + Print("Counter overflow detected\n"); + // Exit(); + } + } +} + +// Initializing the ChaCha20 context +U0 chacha20_init_context(chacha20_context *ctx, U8 *key, U8 *nonce, U64 counter) { + MemSet(ctx, 0, sizeof(chacha20_context)); + + chacha20_init_block(ctx, key, nonce); + chacha20_block_set_counter(ctx, counter); + + ctx->counter = counter; + ctx->position = 64; +} + + +// XOR operation for ChaCha20 +U0 chacha20_xor(chacha20_context *ctx, U8 *bytes, U64 n_bytes) { + U8 *keystream8 = ctx->keystream32(U8*); + // was U64 for some reason? + I64 i; + for (i = 0; i < n_bytes; i++) { + if (ctx->position >= 64) { + chacha20_block_next(ctx); + ctx->position = 0; + } + bytes[i] ^= keystream8[ctx->position++]; + } +} + + +// Define key and nonce. Ensure they are the correct size (key: 32 bytes, nonce: 12 bytes). +U8 key[32] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F +}; +U8 nonce[12] = { + 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x4A, + 0x00, 0x00, 0x00, 0x00 +}; + +U0 Main() { + I64 i; + // Define the plaintext message + U8 plaintext[16] = "Hello, TempleOS!"; + U64 plaintext_len = sizeof(plaintext); + + // Allocate space for the ciphertext (same size as plaintext) + U8 ciphertext[16]; + + // Initialize ChaCha20 context + chacha20_context ctx; + chacha20_init_context(&ctx, key, nonce, 0); // Counter starts at 0 + + // Encrypt the plaintext + MemCopy(ciphertext, plaintext, plaintext_len); // Copy plaintext to ciphertext buffer + chacha20_xor(&ctx, ciphertext, plaintext_len); // Perform XOR operation + + // Output the encrypted message + "Encrypted Message: "; + for (i = 0; i < plaintext_len; i++) { + "%02X ", ciphertext[i]; + } + "\n"; + + // Decrypt the ciphertext (same operation as encryption) + chacha20_init_context(&ctx, key, nonce, 0); // Reinitialize context for decryption + U8 decrypted[plaintext_len]; + MemCopy(decrypted, ciphertext, plaintext_len); // Copy ciphertext to decrypted buffer + chacha20_xor(&ctx, decrypted, plaintext_len); // Perform XOR operation + + // Output the decrypted message + "Decrypted Message: "; + for (i = 0; i < plaintext_len; i++) { + "%c", decrypted[i]; + } + "\n"; +} + +Main; \ No newline at end of file diff --git a/src/Home/Crypto/TweetNaCl/TweetNaCl.HH b/src/Home/Crypto/TweetNaCl/TweetNaCl.HH new file mode 100644 index 00000000..1a1ddcfb --- /dev/null +++ b/src/Home/Crypto/TweetNaCl/TweetNaCl.HH @@ -0,0 +1,272 @@ +#ifndef TWEETNACL_H +#define TWEETNACL_H +#define crypto_auth_PRIMITIVE "hmacsha512256" +#define crypto_auth crypto_auth_hmacsha512256 +#define crypto_auth_verify crypto_auth_hmacsha512256_verify +#define crypto_auth_BYTES crypto_auth_hmacsha512256_BYTES +#define crypto_auth_KEYBYTES crypto_auth_hmacsha512256_KEYBYTES +#define crypto_auth_IMPLEMENTATION crypto_auth_hmacsha512256_IMPLEMENTATION +#define crypto_auth_VERSION crypto_auth_hmacsha512256_VERSION +#define crypto_auth_hmacsha512256_tweet_BYTES 32 +#define crypto_auth_hmacsha512256_tweet_KEYBYTES 32 +I64 crypto_auth_hmacsha512256_tweet(U8 *, U8 *, I64, U8 *); +I64 crypto_auth_hmacsha512256_tweet_verify(U8 *, U8 *, I64, U8 *); +#define crypto_auth_hmacsha512256_tweet_VERSION "-" +#define crypto_auth_hmacsha512256 crypto_auth_hmacsha512256_tweet +#define crypto_auth_hmacsha512256_verify crypto_auth_hmacsha512256_tweet_verify +#define crypto_auth_hmacsha512256_BYTES crypto_auth_hmacsha512256_tweet_BYTES +#define crypto_auth_hmacsha512256_KEYBYTES crypto_auth_hmacsha512256_tweet_KEYBYTES +#define crypto_auth_hmacsha512256_VERSION crypto_auth_hmacsha512256_tweet_VERSION +#define crypto_auth_hmacsha512256_IMPLEMENTATION "crypto_auth/hmacsha512256/tweet" +#define crypto_box_PRIMITIVE "curve25519xsalsa20poly1305" +#define crypto_box crypto_box_curve25519xsalsa20poly1305 +#define crypto_box_open crypto_box_curve25519xsalsa20poly1305_open +#define crypto_box_keypair crypto_box_curve25519xsalsa20poly1305_keypair +#define crypto_box_beforenm crypto_box_curve25519xsalsa20poly1305_beforenm +#define crypto_box_afternm crypto_box_curve25519xsalsa20poly1305_afternm +#define crypto_box_open_afternm crypto_box_curve25519xsalsa20poly1305_open_afternm +#define crypto_box_PUBLICKEYBYTES crypto_box_curve25519xsalsa20poly1305_PUBLICKEYBYTES +#define crypto_box_SECRETKEYBYTES crypto_box_curve25519xsalsa20poly1305_SECRETKEYBYTES +#define crypto_box_BEFORENMBYTES crypto_box_curve25519xsalsa20poly1305_BEFORENMBYTES +#define crypto_box_NONCEBYTES crypto_box_curve25519xsalsa20poly1305_NONCEBYTES +#define crypto_box_ZEROBYTES crypto_box_curve25519xsalsa20poly1305_ZEROBYTES +#define crypto_box_BOXZEROBYTES crypto_box_curve25519xsalsa20poly1305_BOXZEROBYTES +#define crypto_box_IMPLEMENTATION crypto_box_curve25519xsalsa20poly1305_IMPLEMENTATION +#define crypto_box_VERSION crypto_box_curve25519xsalsa20poly1305_VERSION +#define crypto_box_curve25519xsalsa20poly1305_tweet_PUBLICKEYBYTES 32 +#define crypto_box_curve25519xsalsa20poly1305_tweet_SECRETKEYBYTES 32 +#define crypto_box_curve25519xsalsa20poly1305_tweet_BEFORENMBYTES 32 +#define crypto_box_curve25519xsalsa20poly1305_tweet_NONCEBYTES 24 +#define crypto_box_curve25519xsalsa20poly1305_tweet_ZEROBYTES 32 +#define crypto_box_curve25519xsalsa20poly1305_tweet_BOXZEROBYTES 16 +I64 crypto_box_curve25519xsalsa20poly1305_tweet(U8 *, U8 *, I64, U8 *, U8 *, U8 *); +I64 crypto_box_curve25519xsalsa20poly1305_tweet_open(U8 *, U8 *, I64, U8 *, U8 *, U8 *); +I64 crypto_box_curve25519xsalsa20poly1305_tweet_keypair(U8 *, U8 *); +I64 crypto_box_curve25519xsalsa20poly1305_tweet_beforenm(U8 *, U8 *, U8 *); +I64 crypto_box_curve25519xsalsa20poly1305_tweet_afternm(U8 *, U8 *, I64, U8 *, U8 *); +I64 crypto_box_curve25519xsalsa20poly1305_tweet_open_afternm(U8 *, U8 *, I64, U8 *, U8 *); +#define crypto_box_curve25519xsalsa20poly1305_tweet_VERSION "-" +#define crypto_box_curve25519xsalsa20poly1305 crypto_box_curve25519xsalsa20poly1305_tweet +#define crypto_box_curve25519xsalsa20poly1305_open crypto_box_curve25519xsalsa20poly1305_tweet_open +#define crypto_box_curve25519xsalsa20poly1305_keypair crypto_box_curve25519xsalsa20poly1305_tweet_keypair +#define crypto_box_curve25519xsalsa20poly1305_beforenm crypto_box_curve25519xsalsa20poly1305_tweet_beforenm +#define crypto_box_curve25519xsalsa20poly1305_afternm crypto_box_curve25519xsalsa20poly1305_tweet_afternm +#define crypto_box_curve25519xsalsa20poly1305_open_afternm crypto_box_curve25519xsalsa20poly1305_tweet_open_afternm +#define crypto_box_curve25519xsalsa20poly1305_PUBLICKEYBYTES crypto_box_curve25519xsalsa20poly1305_tweet_PUBLICKEYBYTES +#define crypto_box_curve25519xsalsa20poly1305_SECRETKEYBYTES crypto_box_curve25519xsalsa20poly1305_tweet_SECRETKEYBYTES +#define crypto_box_curve25519xsalsa20poly1305_BEFORENMBYTES crypto_box_curve25519xsalsa20poly1305_tweet_BEFORENMBYTES +#define crypto_box_curve25519xsalsa20poly1305_NONCEBYTES crypto_box_curve25519xsalsa20poly1305_tweet_NONCEBYTES +#define crypto_box_curve25519xsalsa20poly1305_ZEROBYTES crypto_box_curve25519xsalsa20poly1305_tweet_ZEROBYTES +#define crypto_box_curve25519xsalsa20poly1305_BOXZEROBYTES crypto_box_curve25519xsalsa20poly1305_tweet_BOXZEROBYTES +#define crypto_box_curve25519xsalsa20poly1305_VERSION crypto_box_curve25519xsalsa20poly1305_tweet_VERSION +#define crypto_box_curve25519xsalsa20poly1305_IMPLEMENTATION "crypto_box/curve25519xsalsa20poly1305/tweet" +#define crypto_core_PRIMITIVE "salsa20" +#define crypto_core crypto_core_salsa20 +#define crypto_core_OUTPUTBYTES crypto_core_salsa20_OUTPUTBYTES +#define crypto_core_INPUTBYTES crypto_core_salsa20_INPUTBYTES +#define crypto_core_KEYBYTES crypto_core_salsa20_KEYBYTES +#define crypto_core_CONSTBYTES crypto_core_salsa20_CONSTBYTES +#define crypto_core_IMPLEMENTATION crypto_core_salsa20_IMPLEMENTATION +#define crypto_core_VERSION crypto_core_salsa20_VERSION +#define crypto_core_salsa20_tweet_OUTPUTBYTES 64 +#define crypto_core_salsa20_tweet_INPUTBYTES 16 +#define crypto_core_salsa20_tweet_KEYBYTES 32 +#define crypto_core_salsa20_tweet_CONSTBYTES 16 +I64 crypto_core_salsa20_tweet(U8 *, U8 *, U8 *, U8 *); +#define crypto_core_salsa20_tweet_VERSION "-" +#define crypto_core_salsa20 crypto_core_salsa20_tweet +#define crypto_core_salsa20_OUTPUTBYTES crypto_core_salsa20_tweet_OUTPUTBYTES +#define crypto_core_salsa20_INPUTBYTES crypto_core_salsa20_tweet_INPUTBYTES +#define crypto_core_salsa20_KEYBYTES crypto_core_salsa20_tweet_KEYBYTES +#define crypto_core_salsa20_CONSTBYTES crypto_core_salsa20_tweet_CONSTBYTES +#define crypto_core_salsa20_VERSION crypto_core_salsa20_tweet_VERSION +#define crypto_core_salsa20_IMPLEMENTATION "crypto_core/salsa20/tweet" +#define crypto_core_hsalsa20_tweet_OUTPUTBYTES 32 +#define crypto_core_hsalsa20_tweet_INPUTBYTES 16 +#define crypto_core_hsalsa20_tweet_KEYBYTES 32 +#define crypto_core_hsalsa20_tweet_CONSTBYTES 16 +I64 crypto_core_hsalsa20_tweet(U8 *, U8 *, U8 *, U8 *); +#define crypto_core_hsalsa20_tweet_VERSION "-" +#define crypto_core_hsalsa20 crypto_core_hsalsa20_tweet +#define crypto_core_hsalsa20_OUTPUTBYTES crypto_core_hsalsa20_tweet_OUTPUTBYTES +#define crypto_core_hsalsa20_INPUTBYTES crypto_core_hsalsa20_tweet_INPUTBYTES +#define crypto_core_hsalsa20_KEYBYTES crypto_core_hsalsa20_tweet_KEYBYTES +#define crypto_core_hsalsa20_CONSTBYTES crypto_core_hsalsa20_tweet_CONSTBYTES +#define crypto_core_hsalsa20_VERSION crypto_core_hsalsa20_tweet_VERSION +#define crypto_core_hsalsa20_IMPLEMENTATION "crypto_core/hsalsa20/tweet" +#define crypto_hashblocks_PRIMITIVE "sha512" +#define crypto_hashblocks crypto_hashblocks_sha512 +#define crypto_hashblocks_STATEBYTES crypto_hashblocks_sha512_STATEBYTES +#define crypto_hashblocks_BLOCKBYTES crypto_hashblocks_sha512_BLOCKBYTES +#define crypto_hashblocks_IMPLEMENTATION crypto_hashblocks_sha512_IMPLEMENTATION +#define crypto_hashblocks_VERSION crypto_hashblocks_sha512_VERSION +#define crypto_hashblocks_sha512_tweet_STATEBYTES 64 +#define crypto_hashblocks_sha512_tweet_BLOCKBYTES 128 +I64 crypto_hashblocks_sha512_tweet(U8 *, U8 *, I64); +#define crypto_hashblocks_sha512_tweet_VERSION "-" +#define crypto_hashblocks_sha512 crypto_hashblocks_sha512_tweet +#define crypto_hashblocks_sha512_STATEBYTES crypto_hashblocks_sha512_tweet_STATEBYTES +#define crypto_hashblocks_sha512_BLOCKBYTES crypto_hashblocks_sha512_tweet_BLOCKBYTES +#define crypto_hashblocks_sha512_VERSION crypto_hashblocks_sha512_tweet_VERSION +#define crypto_hashblocks_sha512_IMPLEMENTATION "crypto_hashblocks/sha512/tweet" +#define crypto_hashblocks_sha256_tweet_STATEBYTES 32 +#define crypto_hashblocks_sha256_tweet_BLOCKBYTES 64 +I64 crypto_hashblocks_sha256_tweet(U8 *, U8 *, I64); +#define crypto_hashblocks_sha256_tweet_VERSION "-" +#define crypto_hashblocks_sha256 crypto_hashblocks_sha256_tweet +#define crypto_hashblocks_sha256_STATEBYTES crypto_hashblocks_sha256_tweet_STATEBYTES +#define crypto_hashblocks_sha256_BLOCKBYTES crypto_hashblocks_sha256_tweet_BLOCKBYTES +#define crypto_hashblocks_sha256_VERSION crypto_hashblocks_sha256_tweet_VERSION +#define crypto_hashblocks_sha256_IMPLEMENTATION "crypto_hashblocks/sha256/tweet" +#define crypto_hash_PRIMITIVE "sha512" +#define crypto_hash crypto_hash_sha512 +#define crypto_hash_BYTES crypto_hash_sha512_BYTES +#define crypto_hash_IMPLEMENTATION crypto_hash_sha512_IMPLEMENTATION +#define crypto_hash_VERSION crypto_hash_sha512_VERSION +#define crypto_hash_sha512_tweet_BYTES 64 +I64 crypto_hash_sha512_tweet(U8 *, U8 *, I64); +#define crypto_hash_sha512_tweet_VERSION "-" +#define crypto_hash_sha512 crypto_hash_sha512_tweet +#define crypto_hash_sha512_BYTES crypto_hash_sha512_tweet_BYTES +#define crypto_hash_sha512_VERSION crypto_hash_sha512_tweet_VERSION +#define crypto_hash_sha512_IMPLEMENTATION "crypto_hash/sha512/tweet" +#define crypto_hash_sha256_tweet_BYTES 32 +I64 crypto_hash_sha256_tweet(U8 *, U8 *, I64); +#define crypto_hash_sha256_tweet_VERSION "-" +#define crypto_hash_sha256 crypto_hash_sha256_tweet +#define crypto_hash_sha256_BYTES crypto_hash_sha256_tweet_BYTES +#define crypto_hash_sha256_VERSION crypto_hash_sha256_tweet_VERSION +#define crypto_hash_sha256_IMPLEMENTATION "crypto_hash/sha256/tweet" +#define crypto_onetimeauth_PRIMITIVE "poly1305" +#define crypto_onetimeauth crypto_onetimeauth_poly1305 +#define crypto_onetimeauth_verify crypto_onetimeauth_poly1305_verify +#define crypto_onetimeauth_BYTES crypto_onetimeauth_poly1305_BYTES +#define crypto_onetimeauth_KEYBYTES crypto_onetimeauth_poly1305_KEYBYTES +#define crypto_onetimeauth_IMPLEMENTATION crypto_onetimeauth_poly1305_IMPLEMENTATION +#define crypto_onetimeauth_VERSION crypto_onetimeauth_poly1305_VERSION +#define crypto_onetimeauth_poly1305_tweet_BYTES 16 +#define crypto_onetimeauth_poly1305_tweet_KEYBYTES 32 +I64 crypto_onetimeauth_poly1305_tweet(U8 *, U8 *, I64, U8 *); +I64 crypto_onetimeauth_poly1305_tweet_verify(U8 *, U8 *, I64, U8 *); +#define crypto_onetimeauth_poly1305_tweet_VERSION "-" +#define crypto_onetimeauth_poly1305 crypto_onetimeauth_poly1305_tweet +#define crypto_onetimeauth_poly1305_verify crypto_onetimeauth_poly1305_tweet_verify +#define crypto_onetimeauth_poly1305_BYTES crypto_onetimeauth_poly1305_tweet_BYTES +#define crypto_onetimeauth_poly1305_KEYBYTES crypto_onetimeauth_poly1305_tweet_KEYBYTES +#define crypto_onetimeauth_poly1305_VERSION crypto_onetimeauth_poly1305_tweet_VERSION +#define crypto_onetimeauth_poly1305_IMPLEMENTATION "crypto_onetimeauth/poly1305/tweet" +#define crypto_scalarmult_PRIMITIVE "curve25519" +#define crypto_scalarmult crypto_scalarmult_curve25519 +#define crypto_scalarmult_base crypto_scalarmult_curve25519_base +#define crypto_scalarmult_BYTES crypto_scalarmult_curve25519_BYTES +#define crypto_scalarmult_SCALARBYTES crypto_scalarmult_curve25519_SCALARBYTES +#define crypto_scalarmult_IMPLEMENTATION crypto_scalarmult_curve25519_IMPLEMENTATION +#define crypto_scalarmult_VERSION crypto_scalarmult_curve25519_VERSION +#define crypto_scalarmult_curve25519_tweet_BYTES 32 +#define crypto_scalarmult_curve25519_tweet_SCALARBYTES 32 +I64 crypto_scalarmult_curve25519_tweet(U8 *, U8 *, U8 *); +I64 crypto_scalarmult_curve25519_tweet_base(U8 *, U8 *); +#define crypto_scalarmult_curve25519_tweet_VERSION "-" +#define crypto_scalarmult_curve25519 crypto_scalarmult_curve25519_tweet +#define crypto_scalarmult_curve25519_base crypto_scalarmult_curve25519_tweet_base +#define crypto_scalarmult_curve25519_BYTES crypto_scalarmult_curve25519_tweet_BYTES +#define crypto_scalarmult_curve25519_SCALARBYTES crypto_scalarmult_curve25519_tweet_SCALARBYTES +#define crypto_scalarmult_curve25519_VERSION crypto_scalarmult_curve25519_tweet_VERSION +#define crypto_scalarmult_curve25519_IMPLEMENTATION "crypto_scalarmult/curve25519/tweet" +#define crypto_secretbox_PRIMITIVE "xsalsa20poly1305" +#define crypto_secretbox crypto_secretbox_xsalsa20poly1305 +#define crypto_secretbox_open crypto_secretbox_xsalsa20poly1305_open +#define crypto_secretbox_KEYBYTES crypto_secretbox_xsalsa20poly1305_KEYBYTES +#define crypto_secretbox_NONCEBYTES crypto_secretbox_xsalsa20poly1305_NONCEBYTES +#define crypto_secretbox_ZEROBYTES crypto_secretbox_xsalsa20poly1305_ZEROBYTES +#define crypto_secretbox_BOXZEROBYTES crypto_secretbox_xsalsa20poly1305_BOXZEROBYTES +#define crypto_secretbox_IMPLEMENTATION crypto_secretbox_xsalsa20poly1305_IMPLEMENTATION +#define crypto_secretbox_VERSION crypto_secretbox_xsalsa20poly1305_VERSION +#define crypto_secretbox_xsalsa20poly1305_tweet_KEYBYTES 32 +#define crypto_secretbox_xsalsa20poly1305_tweet_NONCEBYTES 24 +#define crypto_secretbox_xsalsa20poly1305_tweet_ZEROBYTES 32 +#define crypto_secretbox_xsalsa20poly1305_tweet_BOXZEROBYTES 16 +I64 crypto_secretbox_xsalsa20poly1305_tweet(U8 *, U8 *, I64, U8 *, U8 *); +I64 crypto_secretbox_xsalsa20poly1305_tweet_open(U8 *, U8 *, I64, U8 *, U8 *); +#define crypto_secretbox_xsalsa20poly1305_tweet_VERSION "-" +#define crypto_secretbox_xsalsa20poly1305 crypto_secretbox_xsalsa20poly1305_tweet +#define crypto_secretbox_xsalsa20poly1305_open crypto_secretbox_xsalsa20poly1305_tweet_open +#define crypto_secretbox_xsalsa20poly1305_KEYBYTES crypto_secretbox_xsalsa20poly1305_tweet_KEYBYTES +#define crypto_secretbox_xsalsa20poly1305_NONCEBYTES crypto_secretbox_xsalsa20poly1305_tweet_NONCEBYTES +#define crypto_secretbox_xsalsa20poly1305_ZEROBYTES crypto_secretbox_xsalsa20poly1305_tweet_ZEROBYTES +#define crypto_secretbox_xsalsa20poly1305_BOXZEROBYTES crypto_secretbox_xsalsa20poly1305_tweet_BOXZEROBYTES +#define crypto_secretbox_xsalsa20poly1305_VERSION crypto_secretbox_xsalsa20poly1305_tweet_VERSION +#define crypto_secretbox_xsalsa20poly1305_IMPLEMENTATION "crypto_secretbox/xsalsa20poly1305/tweet" +#define crypto_sign_PRIMITIVE "ed25519" +#define crypto_sign crypto_sign_ed25519 +#define crypto_sign_open crypto_sign_ed25519_open +#define crypto_sign_keypair crypto_sign_ed25519_keypair +#define crypto_sign_BYTES crypto_sign_ed25519_BYTES +#define crypto_sign_PUBLICKEYBYTES crypto_sign_ed25519_PUBLICKEYBYTES +#define crypto_sign_SECRETKEYBYTES crypto_sign_ed25519_SECRETKEYBYTES +#define crypto_sign_IMPLEMENTATION crypto_sign_ed25519_IMPLEMENTATION +#define crypto_sign_VERSION crypto_sign_ed25519_VERSION +#define crypto_sign_ed25519_tweet_BYTES 64 +#define crypto_sign_ed25519_tweet_PUBLICKEYBYTES 32 +#define crypto_sign_ed25519_tweet_SECRETKEYBYTES 64 +I64 crypto_sign_ed25519_tweet(U8 *, I64 *, U8 *, I64, U8 *); +I64 crypto_sign_ed25519_tweet_open(U8 *, I64 *, U8 *, I64, U8 *); +I64 crypto_sign_ed25519_tweet_keypair(U8 *, U8 *); +#define crypto_sign_ed25519_tweet_VERSION "-" +#define crypto_sign_ed25519 crypto_sign_ed25519_tweet +#define crypto_sign_ed25519_open crypto_sign_ed25519_tweet_open +#define crypto_sign_ed25519_keypair crypto_sign_ed25519_tweet_keypair +#define crypto_sign_ed25519_BYTES crypto_sign_ed25519_tweet_BYTES +#define crypto_sign_ed25519_PUBLICKEYBYTES crypto_sign_ed25519_tweet_PUBLICKEYBYTES +#define crypto_sign_ed25519_SECRETKEYBYTES crypto_sign_ed25519_tweet_SECRETKEYBYTES +#define crypto_sign_ed25519_VERSION crypto_sign_ed25519_tweet_VERSION +#define crypto_sign_ed25519_IMPLEMENTATION "crypto_sign/ed25519/tweet" +#define crypto_stream_PRIMITIVE "xsalsa20" +#define crypto_stream crypto_stream_xsalsa20 +#define crypto_stream_xor crypto_stream_xsalsa20_xor +#define crypto_stream_KEYBYTES crypto_stream_xsalsa20_KEYBYTES +#define crypto_stream_NONCEBYTES crypto_stream_xsalsa20_NONCEBYTES +#define crypto_stream_IMPLEMENTATION crypto_stream_xsalsa20_IMPLEMENTATION +#define crypto_stream_VERSION crypto_stream_xsalsa20_VERSION +#define crypto_stream_xsalsa20_tweet_KEYBYTES 32 +#define crypto_stream_xsalsa20_tweet_NONCEBYTES 24 +I64 crypto_stream_xsalsa20_tweet(U8 *, I64, U8 *, U8 *); +I64 crypto_stream_xsalsa20_tweet_xor(U8 *, U8 *, I64, U8 *, U8 *); +#define crypto_stream_xsalsa20_tweet_VERSION "-" +#define crypto_stream_xsalsa20 crypto_stream_xsalsa20_tweet +#define crypto_stream_xsalsa20_xor crypto_stream_xsalsa20_tweet_xor +#define crypto_stream_xsalsa20_KEYBYTES crypto_stream_xsalsa20_tweet_KEYBYTES +#define crypto_stream_xsalsa20_NONCEBYTES crypto_stream_xsalsa20_tweet_NONCEBYTES +#define crypto_stream_xsalsa20_VERSION crypto_stream_xsalsa20_tweet_VERSION +#define crypto_stream_xsalsa20_IMPLEMENTATION "crypto_stream/xsalsa20/tweet" +#define crypto_stream_salsa20_tweet_KEYBYTES 32 +#define crypto_stream_salsa20_tweet_NONCEBYTES 8 +I64 crypto_stream_salsa20_tweet(U8 *, I64, U8 *, U8 *); +I64 crypto_stream_salsa20_tweet_xor(U8 *, U8 *, I64, U8 *, U8 *); +#define crypto_stream_salsa20_tweet_VERSION "-" +#define crypto_stream_salsa20 crypto_stream_salsa20_tweet +#define crypto_stream_salsa20_xor crypto_stream_salsa20_tweet_xor +#define crypto_stream_salsa20_KEYBYTES crypto_stream_salsa20_tweet_KEYBYTES +#define crypto_stream_salsa20_NONCEBYTES crypto_stream_salsa20_tweet_NONCEBYTES +#define crypto_stream_salsa20_VERSION crypto_stream_salsa20_tweet_VERSION +#define crypto_stream_salsa20_IMPLEMENTATION "crypto_stream/salsa20/tweet" +#define crypto_verify_PRIMITIVE "16" +#define crypto_verify crypto_verify_16 +#define crypto_verify_BYTES crypto_verify_16_BYTES +#define crypto_verify_IMPLEMENTATION crypto_verify_16_IMPLEMENTATION +#define crypto_verify_VERSION crypto_verify_16_VERSION +#define crypto_verify_16_tweet_BYTES 16 +I64 crypto_verify_16_tweet(U8 *, U8 *); +#define crypto_verify_16_tweet_VERSION "-" +#define crypto_verify_16 crypto_verify_16_tweet +#define crypto_verify_16_BYTES crypto_verify_16_tweet_BYTES +#define crypto_verify_16_VERSION crypto_verify_16_tweet_VERSION +#define crypto_verify_16_IMPLEMENTATION "crypto_verify/16/tweet" +#define crypto_verify_32_tweet_BYTES 32 +I64 crypto_verify_32_tweet(U8 *, U8 *); +#define crypto_verify_32_tweet_VERSION "-" +#define crypto_verify_32 crypto_verify_32_tweet +#define crypto_verify_32_BYTES crypto_verify_32_tweet_BYTES +#define crypto_verify_32_VERSION crypto_verify_32_tweet_VERSION +#define crypto_verify_32_IMPLEMENTATION "crypto_verify/32/tweet" +#endif \ No newline at end of file diff --git a/src/Home/Crypto/TweetNaCl/TweetNaCl.ZC b/src/Home/Crypto/TweetNaCl/TweetNaCl.ZC new file mode 100644 index 00000000..d747a69f --- /dev/null +++ b/src/Home/Crypto/TweetNaCl/TweetNaCl.ZC @@ -0,0 +1,875 @@ +// Cd(__DIR__);; +// #include "TweetNaCl.HH" +// U0 randombytes(U8 *, U64); +U0 randombytes(U8 *array, U64 length) { + U64 i; + for (i = 0; i < length; i++) { + array[i] = RandU8(); + } +} + +class gf { + I64 data[16]; +}; + + +U8 _0[16]; +U8 _9[32] = {9, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0 + }; + + +gf gf0; +gf gf1; +gf _121665; +gf D; +gf D2; +gf X; +gf Y; +gf I; + +U0 InitGf() { + // Initialize gf1 + I64 i; + gf1.data[0] = 1; + for (i = 1; i < 16; i++) gf1.data[i] = 0; + + // Initialize _121665 + _121665.data[0] = 0xDB41; + _121665.data[1] = 1; + for (i = 2; i < 16; i++) _121665.data[i] = 0; + + // Initialize D + D.data[0] = 0x78a3; D.data[1] = 0x1359; D.data[2] = 0x4dca; D.data[3] = 0x75eb; + D.data[4] = 0xd8ab; D.data[5] = 0x4141; D.data[6] = 0x0a4d; D.data[7] = 0x0070; + D.data[8] = 0xe898; D.data[9] = 0x7779; D.data[10] = 0x4079; D.data[11] = 0x8cc7; + D.data[12] = 0xfe73; D.data[13] = 0x2b6f; D.data[14] = 0x6cee; D.data[15] = 0x5203; + + // Initialize D2 + D2.data[0] = 0xf159; D2.data[1] = 0x26b2; D2.data[2] = 0x9b94; D2.data[3] = 0xebd6; + D2.data[4] = 0xb156; D2.data[5] = 0x8283; D2.data[6] = 0x149a; D2.data[7] = 0x00e0; + D2.data[8] = 0xd130; D2.data[9] = 0xeef3; D2.data[10] = 0x80f2; D2.data[11] = 0x198e; + D2.data[12] = 0xfce7; D2.data[13] = 0x56df; D2.data[14] = 0xd9dc; D2.data[15] = 0x2406; + + // Initialize X + X.data[0] = 0xd51a; X.data[1] = 0x8f25; X.data[2] = 0x2d60; X.data[3] = 0xc956; + X.data[4] = 0xa7b2; X.data[5] = 0x9525; X.data[6] = 0xc760; X.data[7] = 0x692c; + X.data[8] = 0xdc5c; X.data[9] = 0xfdd6; X.data[10] = 0xe231; X.data[11] = 0xc0a4; + X.data[12] = 0x53fe; X.data[13] = 0xcd6e; X.data[14] = 0x36d3; X.data[15] = 0x2169; + + // Initialize Y + Y.data[0] = 0x6658; Y.data[1] = 0x6666; Y.data[2] = 0x6666; Y.data[3] = 0x6666; + Y.data[4] = 0x6666; Y.data[5] = 0x6666; Y.data[6] = 0x6666; Y.data[7] = 0x6666; + Y.data[8] = 0x6666; Y.data[9] = 0x6666; Y.data[10] = 0x6666; Y.data[11] = 0x6666; + Y.data[12] = 0x6666; Y.data[13] = 0x6666; Y.data[14] = 0x6666; Y.data[15] = 0x6666; + + // Initialize I + I.data[0] = 0xa0b0; I.data[1] = 0x4a0e; I.data[2] = 0x1b27; I.data[3] = 0xc4ee; + I.data[4] = 0xe478; I.data[5] = 0xad2f; I.data[6] = 0x1806; I.data[7] = 0x2f43; + I.data[8] = 0xd7a7; I.data[9] = 0x3dfb; I.data[10] = 0x0099; I.data[11] = 0x2b4d; + I.data[12] = 0xdf0b; I.data[13] = 0x4fc1; I.data[14] = 0x2480; I.data[15] = 0x2b83; +} + +InitGf; + +U32 L32(U32 x, I64 c) { return (x << c) | ((x & 0xffffffff) >> (32 - c)); } + +U32 Ld32(U8 *x) +{ + U32 u = x[3]; + u = (u << 8) | x[2]; + u = (u << 8) | x[1]; + return (u << 8) | x[0]; +} + +U64 Dl64(U8 *x) { + U64 i, u = 0; + for (i = 0;i < 8;++i) u |= x[i] << 8 * i; // (U64) x[i] << 8 * i; + return u; +} + +U0 St32(U8 *x, U32 u) { + I64 i; + for (i = 0;i < 4;++i) { x[i] = u; u >>= 8; } +} + +U0 ts64(U8 *x, U64 u) { + I64 i; + for (i = 7; i >= 0; --i) { x[i] = u; u >>= 8; } +} + +I64 vn(U8 *x, U8 *y, I64 n) { + U32 i, d = 0; + for (i = 0;i < n;++i) d |= x[i] ^ y[i]; + return (1 & ((d - 1) >> 8)) - 1; +} + +I64 crypto_verify_16(U8 *x, U8 *y) { + return vn(x, y, 16); +} + +I64 crypto_verify_32(U8 *x, U8 *y) { + return vn(x, y, 32); +} + +U0 core(U8 *out, U8 *in, U8 *k, U8 *c, I64 h) { + U32 w[16], x[16], y[16], t[4]; + I64 i, j, m; + + for(i=0;i < 4;++i){ + x[5 * i] = Ld32(c + 4 * i); + x[1 + i] = Ld32(k + 4 * i); + x[6 + i] = Ld32(in + 4 * i); + x[11 + i] = Ld32(k + 16 + 4 * i); + } + + for(i=0;i < 16;++i) y[i] = x[i]; + for(i=0;i < 20;++i){ + for(j=0;j < 4;++j){ + for(m=0;m < 4;++m) t[m] = x[(5 * j + 4 * m) % 16]; + t[1] ^= L32(t[0] + t[3], 7); + t[2] ^= L32(t[1] + t[0], 9); + t[3] ^= L32(t[2] + t[1], 13); + t[0] ^= L32(t[3] + t[2], 18); + for(m=0;m < 4;++m) w[4 * j + (j + m) % 4] = t[m]; + } + for(m=0;m < 16;++m) x[m] = w[m]; + } + + if (h) { + for(i=0;i < 16;++i) x[i] += y[i]; + for(i=0;i < 4;++i) { + x[5 * i] -= Ld32(c + 4 * i); + x[6 + i] -= Ld32(in + 4 * i); + } + for(i=0;i < 4;++i) { + St32(out + 4 * i, x[5 * i]); + St32(out + 16 + 4 * i, x[6 + i]); + } + } else { + for(i=0;i < 16;++i) St32(out + 4 * i, x[i] + y[i]); + } +} + +I64 crypto_core_salsa20(U8 *out, U8 *in, U8 *k, U8 *c) { + core(out, in, k, c, 0); + return 0; +} + +I64 crypto_core_hsalsa20(U8 *out, U8 *in, U8 *k, U8 *c) { + core(out, in, k, c, 1); + return 0; +} + +U8 sigma[16] = "expand 32-byte k"; + +I64 crypto_stream_salsa20_xor(U8 *c, U8 *m, U64 b, U8 *n, U8 *k) { + U8 z[16], x[64]; + U32 u, i; + if (!b) return 0; + for (i = 0;i < 16;++i) z[i] = 0; + for (i = 0;i < 8;++i) z[i] = n[i]; + while (b >= 64) { + crypto_core_salsa20(x, z, k, sigma); + for (i = 0;i < 64;++i){ + if (m != NULL) { + c[i] = m[i] ^ x[i]; + } else { + c[i] = 0 ^ x[i]; + } + } + // c[i] = (m ? m[i] : 0) ^ x[i]; + u = 1; + for (i = 8; i < 16; ++i) { + u += z[i]; // (u32 z[i]) + z[i] = u; + u >>= 8; + } + b -= 64; + c += 64; + if (m) m += 64; + } + if (b) { + crypto_core_salsa20(x, z, k, sigma); + for (i = 0;i < b;++i) { + // c[i] = (m ? m[i] : 0) ^ x[i]; + if (m != NULL) { + c[i] = m[i] ^ x[i]; + } else { + c[i] = 0 ^ x[i]; + } + } + } + return 0; +} + +I64 crypto_stream_salsa20(U8 *c, U64 d, U8 *n, U8 *k) { + return crypto_stream_salsa20_xor(c, 0, d, n, k); +} + +I64 crypto_stream(U8 *c, U64 d, U8 *n, U8 *k) { + U8 s[32]; + crypto_core_hsalsa20(s, n, k, sigma); + return crypto_stream_salsa20(c, d, n + 16, s); +} + +I64 crypto_stream_xor(U8 *c, U8 *m, U64 d, U8 *n, U8 *k) { + U8 s[32]; + crypto_core_hsalsa20(s, n, k, sigma); + return crypto_stream_salsa20_xor(c, m, d, n + 16, s); +} + +U0 add1305(U32 *h, U32 *c) { + U32 j, u = 0; + for (j = 0;j < 17;++j){ + u += h[j] + c[j]; + h[j] = u & 255; + u >>= 8; + } +} + +U32 minusp[17] = { + 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 252 +}; + +I64 crypto_onetimeauth(U8 *out, U8 *m, U64 n, U8 *k) { + U32 s, i, j, u, x[17], r[17], h[17], c[17], g[17]; + + for (j = 0;j < 17;++j) r[j] = h[j] = 0; + for (j = 0;j < 16;++j) r[j] = k[j]; + r[3]&=15; + r[4]&=252; + r[7]&=15; + r[8]&=252; + r[11]&=15; + r[12]&=252; + r[15]&=15; + + while (n > 0) { + for (j = 0;j < 17;++j) c[j] = 0; + for (j = 0; (j < 16) && (j < n); ++j) c[j] = m[j]; + c[j] = 1; + m += j; n -= j; + add1305(h, c); + for (i = 0;i < 17;++i) { + x[i] = 0; + for (j = 0;j < 17;++j) { + if (j <= i) { + x[i] += h[j] * r[i - j]; + } else { + x[i] += h[j] * (320 * r[i + 17 - j]); + } + } + } + for (i = 0;i < 17;++i) h[i] = x[i]; + u = 0; + for (j = 0;j < 16;++j) { + u += h[j]; + h[j] = u & 255; + u >>= 8; + } + u += h[16]; h[16] = u & 3; + u = 5 * (u >> 2); + for (j = 0;j < 16;++j) { + u += h[j]; + h[j] = u & 255; + u >>= 8; + } + u += h[16]; h[16] = u; + } + for (j = 0;j < 17;++j) g[j] = h[j]; + add1305(h, minusp); + s = -(h[16] >> 7); + for (j = 0;j < 17;++j) h[j] ^= s & (g[j] ^ h[j]); + for (j = 0;j < 16;++j) c[j] = k[j + 16]; + c[16] = 0; + add1305(h, c); + for (j = 0;j < 16;++j) out[j] = h[j]; + return 0; +} + +I64 crypto_onetimeauth_verify(U8 *h, U8 *m, U64 n, U8 *k) { + U8 x[16]; + crypto_onetimeauth(x, m, n, k); + return crypto_verify_16(h, x); +} + +I64 crypto_secretbox(U8 *c, U8 *m, U64 d, U8 *n, U8 *k) { + I64 i; + if (d < 32) return -1; + crypto_stream_xor(c, m, d, n, k); + crypto_onetimeauth(c + 16, c + 32, d - 32, c); + for (i = 0;i < 16;++i) c[i] = 0; + return 0; +} + +I64 crypto_secretbox_open(U8 *m, U8 *c, U64 d, U8 *n, U8 *k) { + I64 i; + U8 x[32]; + if (d < 32) return -1; + crypto_stream(x, 32, n, k); + if (crypto_onetimeauth_verify(c + 16, c + 32, d - 32, x) != 0) return -1; + crypto_stream_xor(m, c, d, n, k); + for (i = 0;i < 32;++i) m[i] = 0; + return 0; +} + +U0 Set25519(gf r, gf a) { + I64 i; + for (i = 0; i < 16; ++i) { + r.data[i] = a.data[i]; + } +} + +U0 Car25519(gf o) { + I64 i, c; + for (i = 0; i < 16; ++i) { + o.data[i] += (1 << 16); + c = o.data[i] >> 16; + o.data[(i + 1) * (i < 15)] += c - 1 + 37 * (c - 1) * (i == 15); + o.data[i] -= c << 16; + } +} + +U0 Sel25519(gf p, gf q, I64 b) { + I64 t, i, c = ~(b - 1); + for (i = 0; i < 16; ++i) { + t = c & (p.data[i] ^ q.data[i]); + p.data[i] ^= t; + q.data[i] ^= t; + } +} + +U0 Pack25519(U8 *o, I64 *n) { + I64 i, j, b; + I64 m[16], t[16]; + + for (i = 0; i < 16; ++i) { + t[i] = n[i]; + } + Car25519(t); + Car25519(t); + Car25519(t); + + for (j = 0; j < 2; ++j) { + m[0] = t[0] - 0xffed; + for (i = 1; i < 15; i++) { + m[i] = t[i] - 0xffff - ((m[i - 1] >> 16) & 1); + m[i - 1] &= 0xffff; + } + m[15] = t[15] - 0x7fff - ((m[14] >> 16) & 1); + b = (m[15] >> 16) & 1; + m[14] &= 0xffff; + Sel25519(t, m, 1 - b); + } + + for (i = 0; i < 16; ++i) { + o[2 * i] = t[i] & 0xff; + o[2 * i + 1] = t[i] >> 8; + } +} + +I64 Neq25519(gf a, gf b) { + U8 c[32], d[32]; + Pack25519(c, a); + Pack25519(d, b); + return crypto_verify_32(c, d); +} + +U8 Par25519(gf a) { + U8 d[32]; + Pack25519(d, a); + return d[0] & 1; +} + +U0 Unpack25519(gf o, U8 *n) { + I64 i; + for(i=0;i<16;++i) { + o.data[i] = n[2 * i] + (n[2 * i + 1] << 8); + } + o.data[15] &= 0x7fff; +} + +// addition +U0 A(gf o, gf a, gf b) +{ + I64 i; + for (i = 0;i < 16;++i) o.data[i] = a.data[i] + b.data[i]; +} + +// substraction +U0 Z(gf o, gf a, gf b) { + I64 i; + for (i = 0;i < 16;++i) o.data[i] = a.data[i] - b.data[i]; +} +// multiply +U0 M(gf o, gf a, gf b) { + I64 i, j, t[31]; + for (i = 0;i < 31;++i) t[i] = 0; + for (i = 0;i < 16;++i) { for (j = 0;j < 16;++j) {t[i + j] += a.data[i] * b.data[j];} } + for (i = 0;i < 15;++i) t[i] += 38 * t[i + 16]; + for (i = 0;i < 16;++i) o.data[i] = t[i]; + Car25519(o); + Car25519(o); +} +// square +U0 S(gf o, gf a) { + M(o, a, a); +} + +U0 Inv25519(gf *o, gf i) { + gf c; + I64 a; + + for (a = 0; a < 16; ++a) c.data[a] = i.data[a]; + for (a = 253; a >= 0; --a) { + S(c.data, c.data); + if (a != 2 && a != 4) M(c.data, c.data, i.data); + } + for (a = 0; a < 16; ++a) o->data[a] = c.data[a]; +} + +U0 Pow2523(gf *o, gf i) { + gf c; + I64 a; + + for (a = 0; a < 16; ++a) c.data[a] = i.data[a]; + for (a = 250; a >= 0; --a) { + S(c.data, c.data); + if (a != 1) M(c.data, c.data, i.data); + } + for (a = 0; a < 16; ++a) o->data[a] = c.data[a]; +} + +U0 Add(gf *p, gf *q) { + gf a, b, c, d, t, e, f, g, h; + + Z(a, p[1], p[0]); + Z(t, q[1], q[0]); + M(a, a, t); + A(b, p[0], p[1]); + A(t, q[0], q[1]); + M(b, b, t); + M(c, p[3], q[3]); + M(c, c, D2); + M(d, p[2], q[2]); + A(d, d, d); + Z(e, b, a); + Z(f, d, c); + A(g, d, c); + A(h, b, a); + + M(p[0], e, f); + M(p[1], h, g); + M(p[2], g, f); + M(p[3], e, h); +} + +U0 Cswap(gf *p, gf *q, U8 b) { + I64 i; + for (i = 0; i < 4; ++i) { + Sel25519(p[i].data, q[i].data, b); + } +} + +U0 Pack(U8 *r, gf *p) { + gf tx, ty, zi; + Inv25519(zi, p[2]); + M(tx, p[0], zi); + M(ty, p[1], zi); + Pack25519(r, ty); + r[31] ^= Par25519(tx) << 7; +} + +U0 Scalarmult(gf *p, gf q, U8 *s) { + I64 i; + Set25519(p[0], gf0); + Set25519(p[1], gf1); + Set25519(p[2], gf1); + Set25519(p[3], gf0); + for (i = 255; i >= 0; --i) { + U8 b = (s[i / 8] >> (i & 7)) & 1; + Cswap(p, q, b); + Add(q, p); + Add(p, p); + Cswap(p, q, b); + } +} + +U0 Scalarbase(gf *p, U8 *s) { + gf q[4]; + Set25519(q[0], X); + Set25519(q[1], Y); + Set25519(q[2], gf1); + M(q[3], X, Y); + Scalarmult(p, q, s); +} + +I64 crypto_sign_keypair(U8 *pk, U8 *sk) +{ + U8 d[64]; + gf p[4]; + I64 i; + + randombytes(sk, 32); + crypto_hash(d, sk, 32); + d[0] &= 248; + d[31] &= 127; + d[31] |= 64; + + Scalarbase(p,d); + Pack(pk,p); + + for (i = 0; i < 32; i++) sk[32 + i] = pk[i]; + return 0; +} + + +I64 crypto_Scalarmult(U8 *q, U8 *n, U8 *p) { + U8 z[32]; + I64 x[80], r, i; + gf a, b, c, d, e, f; + + for (i = 0; i < 31; ++i) { + z[i] = n[i]; + } + z[31] = (n[31] & 127) | 64; + z[0] &= 248; + + Unpack25519(x, p); + + for (i = 0; i < 16; ++i) { + d.data[i] = a.data[i] = c.data[i] = 0; + } + a.data[0] = d.data[0] = 1; + + for (i = 254; i >= 0; --i) { + r = (z[i >> 3] >> (i & 7)) & 1; + Sel25519(a.data,b.data,r); + Sel25519(c.data,d.data,r); + A(e,a,c); + Z(a,a,c); + A(c,b,d); + Z(b,b,d); + S(d,e); + S(f,a); + M(a,c,a); + M(c,b,e); + A(e,a,c); + Z(a,a,c); + S(b,a); + Z(c,d,f); + M(a,c,_121665); + A(a,a,d); + M(c,c,a); + M(a,d,f); + M(d,b,x); + S(b,e); + Sel25519(a.data,b.data,r); + Sel25519(c.data,d.data,r); + } + + Inv25519(x+32, c+32); + M(x+16, a+16, x+32); + Pack25519(q, x+16); + + return 0; +} + +I64 crypto_Scalarmult_base(U8 *q, U8 *n) { + return crypto_Scalarmult(q, n, _9); +} + +I64 crypto_box_keypair(U8 *y, U8 *x) { + randombytes(x, 32); + return crypto_Scalarmult_base(y, x); +} + +I64 crypto_box_beforenm(U8 *k, U8 *y, U8 *x) { + U8 s[32]; + crypto_Scalarmult(s, x, y); + return crypto_core_hsalsa20(k, _0, s, sigma); +} + +I64 crypto_box_afternm(U8 *c, U8 *m, U64 d, U8 *n, U8 *k) { + return crypto_secretbox(c, m, d, n, k); +} + +I64 crypto_box_open_afternm(U8 *m, U8 *c, U64 d, U8 *n, U8 *k) { + return crypto_secretbox_open(m, c, d, n, k); +} + +I64 crypto_box(U8 *c, U8 *m, U64 d, U8 *n, U8 *y, U8 *x) { + U8 k[32]; + crypto_box_beforenm(k, y, x); + return crypto_box_afternm(c, m, d, n, k); +} + +I64 crypto_box_open(U8 *m, U8 *c, U64 d, U8 *n, U8 *y, U8 *x) { + U8 k[32]; + crypto_box_beforenm(k, y, x); + return crypto_box_open_afternm(m, c, d, n, k); +} + +U64 R(U64 x, I64 c) { return (x >> c) | (x << (64 - c)); } +U64 Ch(U64 x, U64 y, U64 z) { return (x & y) ^ (~x & z); } +U64 Maj(U64 x, U64 y, U64 z) { return (x & y) ^ (x & z) ^ (y & z); } +U64 Sigma0(U64 x) { return R(x, 28) ^ R(x, 34) ^ R(x, 39); } +U64 Sigma1(U64 x) { return R(x, 14) ^ R(x, 18) ^ R(x, 41); } +U64 sigma0(U64 x) { return R(x, 1) ^ R(x, 8) ^ (x >> 7); } +U64 sigma1(U64 x) { return R(x, 19) ^ R(x, 61) ^ (x >> 6); } + +U64 K[80] = +{ + 0x428a2f98d728ae22, 0x7137449123ef65cd, 0xb5c0fbcfec4d3b2f, 0xe9b5dba58189dbbc, + 0x3956c25bf348b538, 0x59f111f1b605d019, 0x923f82a4af194f9b, 0xab1c5ed5da6d8118, + 0xd807aa98a3030242, 0x12835b0145706fbe, 0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2, + 0x72be5d74f27b896f, 0x80deb1fe3b1696b1, 0x9bdc06a725c71235, 0xc19bf174cf692694, + 0xe49b69c19ef14ad2, 0xefbe4786384f25e3, 0x0fc19dc68b8cd5b5, 0x240ca1cc77ac9c65, + 0x2de92c6f592b0275, 0x4a7484aa6ea6e483, 0x5cb0a9dcbd41fbd4, 0x76f988da831153b5, + 0x983e5152ee66dfab, 0xa831c66d2db43210, 0xb00327c898fb213f, 0xbf597fc7beef0ee4, + 0xc6e00bf33da88fc2, 0xd5a79147930aa725, 0x06ca6351e003826f, 0x142929670a0e6e70, + 0x27b70a8546d22ffc, 0x2e1b21385c26c926, 0x4d2c6dfc5ac42aed, 0x53380d139d95b3df, + 0x650a73548baf63de, 0x766a0abb3c77b2a8, 0x81c2c92e47edaee6, 0x92722c851482353b, + 0xa2bfe8a14cf10364, 0xa81a664bbc423001, 0xc24b8b70d0f89791, 0xc76c51a30654be30, + 0xd192e819d6ef5218, 0xd69906245565a910, 0xf40e35855771202a, 0x106aa07032bbd1b8, + 0x19a4c116b8d2d0c8, 0x1e376c085141ab53, 0x2748774cdf8eeb99, 0x34b0bcb5e19b48a8, + 0x391c0cb3c5c95a63, 0x4ed8aa4ae3418acb, 0x5b9cca4f7763e373, 0x682e6ff3d6b2b8a3, + 0x748f82ee5defb2fc, 0x78a5636f43172f60, 0x84c87814a1f0ab72, 0x8cc702081a6439ec, + 0x90befffa23631e28, 0xa4506cebde82bde9, 0xbef9a3f7b2c67915, 0xc67178f2e372532b, + 0xca273eceea26619c, 0xd186b8c721c0c207, 0xeada7dd6cde0eb1e, 0xf57d4f7fee6ed178, + 0x06f067aa72176fba, 0x0a637dc5a2c898a6, 0x113f9804bef90dae, 0x1b710b35131c471b, + 0x28db77f523047d84, 0x32caab7b40c72493, 0x3c9ebe0a15c9bebc, 0x431d67c49c100d4c, + 0x4cc5d4becb3e42b6, 0x597f299cfc657e2a, 0x5fcb6fab3ad6faec, 0x6c44198c4a475817 +}; + +I64 crypto_hashblocks(U8 *x, U8 *m, U64 n) { + U64 z[8], b[8], a[8], w[16], t; + I64 i, j; + + for (i = 0;i < 8;++i) z[i] = a[i] = Dl64(x + 8 * i); + + while (n >= 128) { + for (i = 0;i < 16;++i) w[i] = Dl64(m + 8 * i); + + for (i = 0;i < 80;++i) { + for (j = 0;j < 8;++j) b[j] = a[j]; + t = a[7] + Sigma1(a[4]) + Ch(a[4],a[5],a[6]) + K[i] + w[i%16]; + b[7] = t + Sigma0(a[0]) + Maj(a[0],a[1],a[2]); + b[3] += t; + for (j = 0;j < 8;++j) a[(j+1)%8] = b[j]; + if (i%16 == 15) + for (j = 0;j < 16;++j) w[j] += w[(j+9)%16] + sigma0(w[(j+1)%16]) + sigma1(w[(j+14)%16]); + } + + for (i = 0;i < 8;++i) { a[i] += z[i]; z[i] = a[i]; } + + m += 128; + n -= 128; + } + + for (i = 0;i < 8;++i) ts64(x + 8 * i, z[i]); + + return n; +} +U8 iv[64] = { + 0x6a,0x09,0xe6,0x67,0xf3,0xbc,0xc9,0x08, + 0xbb,0x67,0xae,0x85,0x84,0xca,0xa7,0x3b, + 0x3c,0x6e,0xf3,0x72,0xfe,0x94,0xf8,0x2b, + 0xa5,0x4f,0xf5,0x3a,0x5f,0x1d,0x36,0xf1, + 0x51,0x0e,0x52,0x7f,0xad,0xe6,0x82,0xd1, + 0x9b,0x05,0x68,0x8c,0x2b,0x3e,0x6c,0x1f, + 0x1f,0x83,0xd9,0xab,0xfb,0x41,0xbd,0x6b, + 0x5b,0xe0,0xcd,0x19,0x13,0x7e,0x21,0x79 +}; + +I64 crypto_hash(U8 *out, U8 *m, U64 n) { + U8 h[64], x[256]; + U64 i, b = n; + + for (i = 0;i < 64;++i) h[i] = iv[i]; + + crypto_hashblocks(h, m, n); + m += n; + n &= 127; + m -= n; + + for (i = 0;i < 256;++i) x[i] = 0; + for (i = 0;i < n;++i) x[i] = m[i]; + x[n] = 128; + + n = 256 - 128 * (n < 112); + x[n - 9] = b >> 61; + ts64(x + n - 8, b << 3); + crypto_hashblocks(h, x, n); + for (i = 0;i < 64;++i) out[i] = h[i]; + + return 0; +} + +U0 Add(gf *p, gf *q) { + gf a, b, c, d, t, e, f, g, h; + + Z(a, p[1], p[0]); + Z(t, q[1], q[0]); + M(a, a, t); + A(b, p[0], p[1]); + A(t, q[0], q[1]); + M(b, b, t); + M(c, p[3], q[3]); + M(c, c, D2); + M(d, p[2], q[2]); + A(d, d, d); + Z(e, b, a); + Z(f, d, c); + A(g, d, c); + A(h, b, a); + + M(p[0], e, f); + M(p[1], h, g); + M(p[2], g, f); + M(p[3], e, h); +} + +U64 L[32] = {0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10}; + +U0 modL(U8 *r, I64 *x) { + I64 carry, i, j, index; + for (i = 63; i >= 32; --i) { + carry = 0; + for (j = i - 32; j < i - 12; ++j) { + index = j - (i - 32); + if (index >= 0 && index < 32) { + x[j] += carry - 16 * x[i] * L[index]; + } + carry = (x[j] + 128) >> 8; + x[j] -= carry << 8; + } + x[j] += carry; + x[i] = 0; + } + carry = 0; + for (j = 0; j < 32; j++) { + x[j] += carry - (x[31] >> 4) * L[j]; + carry = x[j] >> 8; + x[j] &= 255; + } + for (j = 0; j < 32; j++) x[j] -= carry * L[j]; + for (i = 0; i < 32; i++) { + x[i+1] += x[i] >> 8; + r[i] = x[i] & 255; + } +} + +U0 reduce(U8 *r) +{ + I64 x[64], i; + for (i = 0; i < 64; i++) x[i] = r[i]; //(U64) r[i]; + for (i = 0; i < 64; i++) r[i] = 0; + modL(r, x); +} + +I64 crypto_sign(U8 *sm, U64 *smlen, U8 *m, U64 n, U8 *sk) +{ + U8 d[64], h[64], r[64]; + I64 i, j, x[64]; + gf p[4]; + + crypto_hash(d, sk, 32); + d[0] &= 248; + d[31] &= 127; + d[31] |= 64; + + *smlen = n+64; + for (i = 0; i < n; i++) sm[64 + i] = m[i]; + for (i = 0; i < 32; i++) sm[32 + i] = d[32 + i]; + + crypto_hash(r, sm+32, n+32); + reduce(r); + Scalarbase(p,r); + Pack(sm,p); + + for (i = 0; i < 32; i++) sm[i+32] = sk[i+32]; + crypto_hash(h,sm,n + 64); + reduce(h); + + for (i = 0; i < 64; i++) x[i] = 0; + for (i = 0; i < 32; i++) x[i] = r[i]; // (U64) r[i]; + for (i = 0; i < 32; i++) for (j = 0; j < 32; j++) x[i+j] += h[i] * d[j]; //x[i+j] += h[i] * (U64) d[j]; + modL(sm + 32,x); + + return 0; +} +I64 UnpackNeg(gf *r, U8 *p) { + gf t, chk, num, den, den2, den4, den6; + Set25519(r[2], gf1); + Unpack25519(r[1], p); + S(num, r[1]); + M(den, num, D); + Z(num, num, r[2]); + A(den, r[2], den); + + S(den2, den); + S(den4, den2); + M(den6, den4, den2); + M(t, den6, num); + M(t, t, den); + + Pow2523(t, t); + M(t, t, num); + M(t, t, den); + M(t, t, den); + M(r[0], t, den); + + S(chk, r[0]); + M(chk, chk, den); + if (Neq25519(chk, num)) M(r[0], r[0], I); + + S(chk, r[0]); + M(chk, chk, den); + if (Neq25519(chk, num)) return -1; + + if (Par25519(r[0]) == (p[31] >> 7)) Z(r[0], gf0, r[0]); + + M(r[3], r[0], r[1]); + return 0; +} + +I64 crypto_sign_open(U8 *m, U64 *mlen, U8 *sm, U64 n, U8 *pk) +{ + I64 i; + U8 t[32], h[64]; + gf p[4], q[4]; + + *mlen = -1; + if (n < 64) return -1; + + if (UnpackNeg(q, pk)) return -1; + + for (i = 0; i < n; i++) m[i] = sm[i]; + for (i = 0; i < 32; i++) m[i+32] = pk[i]; + crypto_hash(h, m, n); + reduce(h); + Scalarmult(p, q, h); + + Scalarbase(q, sm + 32); + Add(p, q); + Pack(t, p); + + n -= 64; + if (crypto_verify_32(sm, t)) { + for (i = 0; i < n; i++) m[i] = 0; + return -1; + } + + for (i = 0; i < n; i++) m[i] = sm[i + 64]; + *mlen = n; + return 0; +} + +// U8 public_key[32]; +// U8 private_key[64]; + +// crypto_box_keypair(public_key, private_key);