Compare commits

...

11 commits

Author SHA1 Message Date
y4my4my4m
998ec863ce
Merge 50a931073b into a95d5559de 2024-10-04 15:31:34 +09:00
y4my4my4m
50a931073b ChaCha20 and put everything in folder 2023-12-29 17:26:08 -05:00
y4my4my4m
2b847de048 AES128 2023-12-28 05:28:23 -05:00
y4my4my4m
8cf3b95bcb update 2023-12-28 01:35:51 -05:00
y4my4my4m
21054dd328 update..or making things worse, who knows 2023-12-28 01:20:54 -05:00
y4my4my4m
2adf8b9103 fix 2023-12-28 00:49:38 -05:00
y4my4my4m
44e4368491 fix 2023-12-28 00:08:41 -05:00
y4my4my4m
ef36afa82b update 2023-12-27 23:16:42 -05:00
y4my4my4m
835a239920 update 2023-12-27 20:57:25 -05:00
y4my4my4m
3577319d2e update 2023-12-27 20:40:30 -05:00
y4my4my4m
d4acf8ee74 init 2023-12-27 20:32:48 -05:00
4 changed files with 1659 additions and 0 deletions

View file

@ -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");

View file

@ -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;

View file

@ -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

View file

@ -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);