misc: Code housekeeping, file restructuring.
This commit is contained in:
@ -22,8 +22,8 @@ Most (**theoretical!**) users should directly use one of the cryptographic *prot
|
|||||||
|
|
||||||
- Advanced Encryption Standard (FIPS 197): AES-128, AES-192, AES-256
|
- Advanced Encryption Standard (FIPS 197): AES-128, AES-192, AES-256
|
||||||
- ChaCha20 (RFC 7539): ChaCha20 with 64-bit nonce and 64-bit counter, ChaCha20 with 96-bit nonce and 32-bit counter
|
- ChaCha20 (RFC 7539): ChaCha20 with 64-bit nonce and 64-bit counter, ChaCha20 with 96-bit nonce and 32-bit counter
|
||||||
- Salsa20: Salsa20/20 with 256-key, Salsa20/20 with 128-bit key
|
- Salsa20 (Bernstein, not standardized): Salsa20/20 with 256-key, Salsa20/20 with 128-bit key
|
||||||
- Secure Hashing Algorithm: SHA-1, SHA-224, SHA-256, SHA-384, SHA-512, SHA-512/224, SHA-512/256
|
- Secure Hash Standard (FIPS 180-4): SHA-1, SHA-224, SHA-256, SHA-384, SHA-512, SHA-512/224, SHA-512/256
|
||||||
|
|
||||||
### Protocols
|
### Protocols
|
||||||
|
|
||||||
@ -40,7 +40,7 @@ Most (**theoretical!**) users should directly use one of the cryptographic *prot
|
|||||||
- DES, 3DES
|
- DES, 3DES
|
||||||
- Block cipher modes: CBC-PKCS7, CFB, OFB, CTR, GCM
|
- Block cipher modes: CBC-PKCS7, CFB, OFB, CTR, GCM
|
||||||
- Poly1305
|
- Poly1305
|
||||||
- SHA-3, HMAC
|
- SHA-512/t, SHA-3, HMAC
|
||||||
- BigIntegers & modular arithmetic
|
- BigIntegers & modular arithmetic
|
||||||
- Cryptographically secure random BigInteger generation & primality testing
|
- Cryptographically secure random BigInteger generation & primality testing
|
||||||
- Elliptic Curve groups (over Fp fields)
|
- Elliptic Curve groups (over Fp fields)
|
||||||
|
|||||||
@ -67,7 +67,7 @@ pub fn build(b: *std.Build) void {
|
|||||||
// Creates a step for unit testing. This only builds the test executable
|
// Creates a step for unit testing. This only builds the test executable
|
||||||
// but does not run it.
|
// but does not run it.
|
||||||
const lib_unit_tests = b.addTest(.{
|
const lib_unit_tests = b.addTest(.{
|
||||||
.root_source_file = b.path("src/root.zig"),
|
.root_source_file = b.path("src/test.zig"),
|
||||||
.target = target,
|
.target = target,
|
||||||
.optimize = optimize,
|
.optimize = optimize,
|
||||||
});
|
});
|
||||||
|
|||||||
@ -63,7 +63,12 @@ const AES_RCON = [_]u32{
|
|||||||
|
|
||||||
// ----------------------------------- ENCRYPTION/DECRYPTION ----------------------------------- //
|
// ----------------------------------- ENCRYPTION/DECRYPTION ----------------------------------- //
|
||||||
|
|
||||||
pub fn aes_encrypt_block(n_rounds: comptime_int, block_in: *const [AES_BLOCK_SIZE]u8, block_out: *[AES_BLOCK_SIZE]u8, expanded_key: *const [4 * (n_rounds + 1)]u32) void {
|
pub fn aes_encrypt_block(
|
||||||
|
n_rounds: comptime_int,
|
||||||
|
block_in: *const [AES_BLOCK_SIZE]u8,
|
||||||
|
block_out: *[AES_BLOCK_SIZE]u8,
|
||||||
|
expanded_key: *const [4 * (n_rounds + 1)]u32,
|
||||||
|
) void {
|
||||||
// Copy input buffer into state (we're treating the buffer as a column-first matrix).
|
// Copy input buffer into state (we're treating the buffer as a column-first matrix).
|
||||||
var state: [AES_BLOCK_SIZE]u8 = undefined;
|
var state: [AES_BLOCK_SIZE]u8 = undefined;
|
||||||
@memcpy(state[0..], block_in);
|
@memcpy(state[0..], block_in);
|
||||||
@ -120,63 +125,121 @@ pub fn aes_decrypt_block(n_rounds: comptime_int, block_in: *const [AES_BLOCK_SIZ
|
|||||||
@memset(state[0..], 0);
|
@memset(state[0..], 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn aes_128_encrypt_block(key: *const [Aes128Parameters.KEY_SIZE]u8, block_in: *const [AES_BLOCK_SIZE]u8, block_out: *[AES_BLOCK_SIZE]u8) void {
|
pub fn aes_128_encrypt_block(
|
||||||
|
key: *const [Aes128Parameters.KEY_SIZE]u8,
|
||||||
|
block_in: *const [AES_BLOCK_SIZE]u8,
|
||||||
|
block_out: *[AES_BLOCK_SIZE]u8,
|
||||||
|
) void {
|
||||||
// Prepare the subkeys for AddRoundKey.
|
// Prepare the subkeys for AddRoundKey.
|
||||||
var expanded_key = aes_128_expand_key(key);
|
var expanded_key = aes_128_expand_key(key);
|
||||||
defer @memset(&expanded_key, 0);
|
defer @memset(&expanded_key, 0);
|
||||||
|
|
||||||
// Call the generic encryption procedure.
|
// Call the generic encryption procedure.
|
||||||
aes_encrypt_block(Aes128Parameters.N_ROUNDS, block_in, block_out, &expanded_key);
|
aes_encrypt_block(
|
||||||
|
Aes128Parameters.N_ROUNDS,
|
||||||
|
block_in,
|
||||||
|
block_out,
|
||||||
|
&expanded_key,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn aes_128_decrypt_block(key: *const [Aes128Parameters.KEY_SIZE]u8, block_in: *const [AES_BLOCK_SIZE]u8, block_out: *[AES_BLOCK_SIZE]u8) void {
|
pub fn aes_128_decrypt_block(
|
||||||
|
key: *const [Aes128Parameters.KEY_SIZE]u8,
|
||||||
|
block_in: *const [AES_BLOCK_SIZE]u8,
|
||||||
|
block_out: *[AES_BLOCK_SIZE]u8,
|
||||||
|
) void {
|
||||||
// Prepare the subkeys for AddRoundKey.
|
// Prepare the subkeys for AddRoundKey.
|
||||||
var expanded_key = aes_128_expand_key(key);
|
var expanded_key = aes_128_expand_key(key);
|
||||||
defer @memset(&expanded_key, 0);
|
defer @memset(&expanded_key, 0);
|
||||||
|
|
||||||
// Call the generic decryption procedure.
|
// Call the generic decryption procedure.
|
||||||
aes_decrypt_block(Aes128Parameters.N_ROUNDS, block_in, block_out, &expanded_key);
|
aes_decrypt_block(
|
||||||
|
Aes128Parameters.N_ROUNDS,
|
||||||
|
block_in,
|
||||||
|
block_out,
|
||||||
|
&expanded_key,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn aes_192_encrypt_block(key: *const [Aes192Parameters.KEY_SIZE]u8, block_in: *const [AES_BLOCK_SIZE]u8, block_out: *[AES_BLOCK_SIZE]u8) void {
|
pub fn aes_192_encrypt_block(
|
||||||
|
key: *const [Aes192Parameters.KEY_SIZE]u8,
|
||||||
|
block_in: *const [AES_BLOCK_SIZE]u8,
|
||||||
|
block_out: *[AES_BLOCK_SIZE]u8,
|
||||||
|
) void {
|
||||||
// Prepare the subkeys for AddRoundKey.
|
// Prepare the subkeys for AddRoundKey.
|
||||||
var expanded_key = aes_192_expand_key(key);
|
var expanded_key = aes_192_expand_key(key);
|
||||||
defer @memset(&expanded_key, 0);
|
defer @memset(&expanded_key, 0);
|
||||||
|
|
||||||
// Call the generic encryption procedure.
|
// Call the generic encryption procedure.
|
||||||
aes_encrypt_block(Aes192Parameters.N_ROUNDS, block_in, block_out, &expanded_key);
|
aes_encrypt_block(
|
||||||
|
Aes192Parameters.N_ROUNDS,
|
||||||
|
block_in,
|
||||||
|
block_out,
|
||||||
|
&expanded_key,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn aes_192_decrypt_block(key: *const [Aes192Parameters.KEY_SIZE]u8, block_in: *const [AES_BLOCK_SIZE]u8, block_out: *[AES_BLOCK_SIZE]u8) void {
|
pub fn aes_192_decrypt_block(
|
||||||
|
key: *const [Aes192Parameters.KEY_SIZE]u8,
|
||||||
|
block_in: *const [AES_BLOCK_SIZE]u8,
|
||||||
|
block_out: *[AES_BLOCK_SIZE]u8,
|
||||||
|
) void {
|
||||||
// Prepare the subkeys for AddRoundKey.
|
// Prepare the subkeys for AddRoundKey.
|
||||||
var expanded_key = aes_192_expand_key(key);
|
var expanded_key = aes_192_expand_key(key);
|
||||||
defer @memset(&expanded_key, 0);
|
defer @memset(&expanded_key, 0);
|
||||||
|
|
||||||
// Call the generic decryption procedure.
|
// Call the generic decryption procedure.
|
||||||
aes_decrypt_block(Aes192Parameters.N_ROUNDS, block_in, block_out, &expanded_key);
|
aes_decrypt_block(
|
||||||
|
Aes192Parameters.N_ROUNDS,
|
||||||
|
block_in,
|
||||||
|
block_out,
|
||||||
|
&expanded_key,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn aes_256_encrypt_block(key: *const [Aes256Parameters.KEY_SIZE]u8, block_in: *const [AES_BLOCK_SIZE]u8, block_out: *[AES_BLOCK_SIZE]u8) void {
|
pub fn aes_256_encrypt_block(
|
||||||
|
key: *const [Aes256Parameters.KEY_SIZE]u8,
|
||||||
|
block_in: *const [AES_BLOCK_SIZE]u8,
|
||||||
|
block_out: *[AES_BLOCK_SIZE]u8,
|
||||||
|
) void {
|
||||||
// Prepare the subkeys for AddRoundKey.
|
// Prepare the subkeys for AddRoundKey.
|
||||||
var expanded_key = aes_256_expand_key(key);
|
var expanded_key = aes_256_expand_key(key);
|
||||||
defer @memset(&expanded_key, 0);
|
defer @memset(&expanded_key, 0);
|
||||||
|
|
||||||
// Call the generic encryption procedure.
|
// Call the generic encryption procedure.
|
||||||
aes_encrypt_block(Aes256Parameters.N_ROUNDS, block_in, block_out, &expanded_key);
|
aes_encrypt_block(
|
||||||
|
Aes256Parameters.N_ROUNDS,
|
||||||
|
block_in,
|
||||||
|
block_out,
|
||||||
|
&expanded_key,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn aes_256_decrypt_block(key: *const [Aes256Parameters.KEY_SIZE]u8, block_in: *const [AES_BLOCK_SIZE]u8, block_out: *[AES_BLOCK_SIZE]u8) void {
|
pub fn aes_256_decrypt_block(
|
||||||
|
key: *const [Aes256Parameters.KEY_SIZE]u8,
|
||||||
|
block_in: *const [AES_BLOCK_SIZE]u8,
|
||||||
|
block_out: *[AES_BLOCK_SIZE]u8,
|
||||||
|
) void {
|
||||||
// Prepare the subkeys for AddRoundKey.
|
// Prepare the subkeys for AddRoundKey.
|
||||||
var expanded_key = aes_256_expand_key(key);
|
var expanded_key = aes_256_expand_key(key);
|
||||||
defer @memset(&expanded_key, 0);
|
defer @memset(&expanded_key, 0);
|
||||||
|
|
||||||
// Call the generic decryption procedure.
|
// Call the generic decryption procedure.
|
||||||
aes_decrypt_block(Aes256Parameters.N_ROUNDS, block_in, block_out, &expanded_key);
|
aes_decrypt_block(
|
||||||
|
Aes256Parameters.N_ROUNDS,
|
||||||
|
block_in,
|
||||||
|
block_out,
|
||||||
|
&expanded_key,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------- KEY EXPANSION ----------------------------------- //
|
// ----------------------------------- KEY EXPANSION ----------------------------------- //
|
||||||
|
|
||||||
pub fn aes_expand_key(n_rounds: comptime_int, n_key_words: comptime_int, key: *const [n_key_words * 4]u8) [4 * (n_rounds + 1)]u32 {
|
pub fn aes_expand_key(
|
||||||
|
n_rounds: comptime_int,
|
||||||
|
n_key_words: comptime_int,
|
||||||
|
key: *const [n_key_words * 4]u8,
|
||||||
|
) [4 * (n_rounds + 1)]u32 {
|
||||||
var expanded_key: [4 * (n_rounds + 1)]u32 = undefined;
|
var expanded_key: [4 * (n_rounds + 1)]u32 = undefined;
|
||||||
|
|
||||||
var i: u32 = 0;
|
var i: u32 = 0;
|
||||||
@ -197,15 +260,27 @@ pub fn aes_expand_key(n_rounds: comptime_int, n_key_words: comptime_int, key: *c
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn aes_128_expand_key(key: *const [Aes128Parameters.KEY_SIZE]u8) [4 * (Aes128Parameters.N_ROUNDS + 1)]u32 {
|
pub fn aes_128_expand_key(key: *const [Aes128Parameters.KEY_SIZE]u8) [4 * (Aes128Parameters.N_ROUNDS + 1)]u32 {
|
||||||
return aes_expand_key(Aes128Parameters.N_ROUNDS, Aes128Parameters.KEY_SIZE / 4, key);
|
return aes_expand_key(
|
||||||
|
Aes128Parameters.N_ROUNDS,
|
||||||
|
Aes128Parameters.KEY_SIZE / 4,
|
||||||
|
key,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn aes_192_expand_key(key: *const [Aes192Parameters.KEY_SIZE]u8) [4 * (Aes192Parameters.N_ROUNDS + 1)]u32 {
|
pub fn aes_192_expand_key(key: *const [Aes192Parameters.KEY_SIZE]u8) [4 * (Aes192Parameters.N_ROUNDS + 1)]u32 {
|
||||||
return aes_expand_key(Aes192Parameters.N_ROUNDS, Aes192Parameters.KEY_SIZE / 4, key);
|
return aes_expand_key(
|
||||||
|
Aes192Parameters.N_ROUNDS,
|
||||||
|
Aes192Parameters.KEY_SIZE / 4,
|
||||||
|
key,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn aes_256_expand_key(key: *const [Aes256Parameters.KEY_SIZE]u8) [4 * (Aes256Parameters.N_ROUNDS + 1)]u32 {
|
pub fn aes_256_expand_key(key: *const [Aes256Parameters.KEY_SIZE]u8) [4 * (Aes256Parameters.N_ROUNDS + 1)]u32 {
|
||||||
return aes_expand_key(Aes256Parameters.N_ROUNDS, Aes256Parameters.KEY_SIZE / 4, key);
|
return aes_expand_key(
|
||||||
|
Aes256Parameters.N_ROUNDS,
|
||||||
|
Aes256Parameters.KEY_SIZE / 4,
|
||||||
|
key,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------- AES OPERATIONS ----------------------------------- //
|
// ----------------------------------- AES OPERATIONS ----------------------------------- //
|
||||||
@ -373,15 +448,12 @@ fn gfmult(factor: comptime_int, element: u8) u8 {
|
|||||||
|
|
||||||
fn word_to_bytes(word: u32) [4]u8 {
|
fn word_to_bytes(word: u32) [4]u8 {
|
||||||
var bytes: [4]u8 = undefined;
|
var bytes: [4]u8 = undefined;
|
||||||
bytes[0] = @truncate(word >> 24);
|
std.mem.writeInt(u32, &bytes, word, .big);
|
||||||
bytes[1] = @truncate(word >> 16);
|
|
||||||
bytes[2] = @truncate(word >> 8);
|
|
||||||
bytes[3] = @truncate(word);
|
|
||||||
return bytes;
|
return bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bytes_to_word(bytes: *const [4]u8) u32 {
|
fn bytes_to_word(bytes: *const [4]u8) u32 {
|
||||||
return (@as(u32, bytes[0]) << 24) | (@as(u32, bytes[1]) << 16) | (@as(u32, bytes[2]) << 8) | @as(u32, bytes[3]);
|
return std.mem.readInt(u32, bytes, .big);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------- TEST VECTORS ----------------------------------- //
|
// ----------------------------------- TEST VECTORS ----------------------------------- //
|
||||||
@ -631,7 +703,7 @@ test "AES SubBytes" {
|
|||||||
};
|
};
|
||||||
|
|
||||||
aes_sub_bytes(&state);
|
aes_sub_bytes(&state);
|
||||||
try testing.expect(std.mem.eql(u8, &state, &reference));
|
try testing.expectEqualSlices(u8, &reference, &state);
|
||||||
}
|
}
|
||||||
|
|
||||||
test "AES ShiftRows" {
|
test "AES ShiftRows" {
|
||||||
@ -645,7 +717,7 @@ test "AES ShiftRows" {
|
|||||||
};
|
};
|
||||||
|
|
||||||
aes_shift_rows(&state);
|
aes_shift_rows(&state);
|
||||||
try testing.expect(std.mem.eql(u8, &state, &reference));
|
try testing.expectEqualSlices(u8, &reference, &state);
|
||||||
}
|
}
|
||||||
|
|
||||||
test "AES MixColumns" {
|
test "AES MixColumns" {
|
||||||
@ -659,7 +731,7 @@ test "AES MixColumns" {
|
|||||||
};
|
};
|
||||||
|
|
||||||
aes_mix_columns(&state);
|
aes_mix_columns(&state);
|
||||||
try testing.expect(std.mem.eql(u8, &state, &reference));
|
try testing.expectEqualSlices(u8, &reference, &state);
|
||||||
}
|
}
|
||||||
|
|
||||||
test "AES InvSubBytes" {
|
test "AES InvSubBytes" {
|
||||||
@ -673,7 +745,7 @@ test "AES InvSubBytes" {
|
|||||||
};
|
};
|
||||||
|
|
||||||
aes_inv_sub_bytes(&state);
|
aes_inv_sub_bytes(&state);
|
||||||
try testing.expect(std.mem.eql(u8, &state, &reference));
|
try testing.expectEqualSlices(u8, &reference, &state);
|
||||||
}
|
}
|
||||||
|
|
||||||
test "AES InvShiftRows" {
|
test "AES InvShiftRows" {
|
||||||
@ -687,7 +759,7 @@ test "AES InvShiftRows" {
|
|||||||
};
|
};
|
||||||
|
|
||||||
aes_inv_shift_rows(&state);
|
aes_inv_shift_rows(&state);
|
||||||
try testing.expect(std.mem.eql(u8, &state, &reference));
|
try testing.expectEqualSlices(u8, &reference, &state);
|
||||||
}
|
}
|
||||||
|
|
||||||
test "AES InvMixColumns" {
|
test "AES InvMixColumns" {
|
||||||
@ -701,5 +773,5 @@ test "AES InvMixColumns" {
|
|||||||
};
|
};
|
||||||
|
|
||||||
aes_inv_mix_columns(&state);
|
aes_inv_mix_columns(&state);
|
||||||
try testing.expect(std.mem.eql(u8, &state, &reference));
|
try testing.expectEqualSlices(u8, &reference, &state);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,15 +4,12 @@ const testing = std.testing;
|
|||||||
// ----------------------------------- DES CONSTANTS ----------------------------------- //
|
// ----------------------------------- DES CONSTANTS ----------------------------------- //
|
||||||
|
|
||||||
pub const DES_BLOCK_SIZE = 64 / 8;
|
pub const DES_BLOCK_SIZE = 64 / 8;
|
||||||
|
|
||||||
pub const DES_TRUE_KEY_SIZE = 56 / 8;
|
pub const DES_TRUE_KEY_SIZE = 56 / 8;
|
||||||
pub const DES_ENCODED_KEY_SIZE = 64 / 8;
|
pub const DES_ENCODED_KEY_SIZE = 64 / 8;
|
||||||
|
pub const DES_N_ROUNDS = 16;
|
||||||
pub const DES_SUBKEY_SIZE = 48 / 8;
|
pub const DES_SUBKEY_SIZE = 48 / 8;
|
||||||
|
|
||||||
pub const DES_N_ROUNDS = 16;
|
const DES_INITIAL_PERMUTATION = [_]u6{
|
||||||
|
|
||||||
pub const DES_INITIAL_PERMUTATION = [_]u6{
|
|
||||||
58, 50, 42, 35, 26, 18, 10, 2,
|
58, 50, 42, 35, 26, 18, 10, 2,
|
||||||
60, 52, 44, 36, 28, 20, 12, 4,
|
60, 52, 44, 36, 28, 20, 12, 4,
|
||||||
62, 54, 46, 38, 30, 22, 14, 6,
|
62, 54, 46, 38, 30, 22, 14, 6,
|
||||||
@ -23,7 +20,7 @@ pub const DES_INITIAL_PERMUTATION = [_]u6{
|
|||||||
63, 55, 47, 39, 31, 23, 15, 7,
|
63, 55, 47, 39, 31, 23, 15, 7,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const DES_INV_INITIAL_PERMUTATION = [_]u6{
|
const DES_INV_INITIAL_PERMUTATION = [_]u6{
|
||||||
40, 8, 48, 16, 56, 24, 64, 32,
|
40, 8, 48, 16, 56, 24, 64, 32,
|
||||||
39, 7, 47, 15, 55, 23, 63, 31,
|
39, 7, 47, 15, 55, 23, 63, 31,
|
||||||
38, 6, 46, 14, 54, 22, 62, 30,
|
38, 6, 46, 14, 54, 22, 62, 30,
|
||||||
@ -34,7 +31,7 @@ pub const DES_INV_INITIAL_PERMUTATION = [_]u6{
|
|||||||
33, 1, 41, 9, 49, 17, 57, 25,
|
33, 1, 41, 9, 49, 17, 57, 25,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const DES_BIT_SELECTION_TABLE_E = [_]u5{
|
const DES_BIT_SELECTION_TABLE_E = [_]u5{
|
||||||
32, 1, 2, 3, 4, 5,
|
32, 1, 2, 3, 4, 5,
|
||||||
4, 5, 6, 7, 8, 9,
|
4, 5, 6, 7, 8, 9,
|
||||||
8, 9, 10, 11, 12, 13,
|
8, 9, 10, 11, 12, 13,
|
||||||
@ -45,14 +42,14 @@ pub const DES_BIT_SELECTION_TABLE_E = [_]u5{
|
|||||||
28, 29, 30, 31, 32, 1,
|
28, 29, 30, 31, 32, 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const DES_PERMUTATION_FUNCTION_P = [_]u5{
|
const DES_PERMUTATION_FUNCTION_P = [_]u5{
|
||||||
16, 7, 20, 21, 29, 12, 28, 17,
|
16, 7, 20, 21, 29, 12, 28, 17,
|
||||||
1, 15, 23, 26, 5, 18, 31, 10,
|
1, 15, 23, 26, 5, 18, 31, 10,
|
||||||
2, 8, 24, 14, 32, 27, 3, 9,
|
2, 8, 24, 14, 32, 27, 3, 9,
|
||||||
19, 13, 30, 6, 22, 11, 4, 25,
|
19, 13, 30, 6, 22, 11, 4, 25,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const DES_KS_SHIFT_SCHEDULE = .{ 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1 };
|
const DES_KS_SHIFT_SCHEDULE = .{ 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1 };
|
||||||
|
|
||||||
// ----------------------------------- ENCRYPTION/DECRYPTION ----------------------------------- //
|
// ----------------------------------- ENCRYPTION/DECRYPTION ----------------------------------- //
|
||||||
|
|
||||||
@ -192,4 +189,4 @@ fn rotate_halves_left(cd: *[DES_TRUE_KEY_SIZE]u8, positions: comptime_int) void
|
|||||||
|
|
||||||
// ----------------------------------- TEST VECTORS ----------------------------------- //
|
// ----------------------------------- TEST VECTORS ----------------------------------- //
|
||||||
|
|
||||||
//
|
// TODO
|
||||||
|
|||||||
2
src/primitive/blockcipher/index.zig
Normal file
2
src/primitive/blockcipher/index.zig
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
pub const aes = @import("aes.zig");
|
||||||
|
pub const des = @import("des.zig");
|
||||||
2
src/primitive/digest/index.zig
Normal file
2
src/primitive/digest/index.zig
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
pub const sha1 = @import("sha_1.zig");
|
||||||
|
pub const sha2 = @import("sha_2.zig");
|
||||||
3
src/primitive/index.zig
Normal file
3
src/primitive/index.zig
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
pub const blockcipher = @import("blockcipher/index.zig");
|
||||||
|
pub const digest = @import("digest/index.zig");
|
||||||
|
pub const streamcipher = @import("streamcipher/index.zig");
|
||||||
@ -222,40 +222,22 @@ pub fn chacha20_block_function(ctx: *ChaCha20Ctx) void {
|
|||||||
// ----------------------------------- LITTLE ENDIAN HELPERS ----------------------------------- //
|
// ----------------------------------- LITTLE ENDIAN HELPERS ----------------------------------- //
|
||||||
|
|
||||||
fn chacha20_serialize(L: comptime_int, words: *const [L]u32, bytes: *[L * 4]u8) void {
|
fn chacha20_serialize(L: comptime_int, words: *const [L]u32, bytes: *[L * 4]u8) void {
|
||||||
if (comptime @import("builtin").target.cpu.arch.endian() == .little) {
|
for (0..L) |i|
|
||||||
@memcpy(bytes, @as(*const [L * 4]u8, @ptrCast(words)));
|
std.mem.writeInt(u32, @ptrCast(bytes[(i * 4)..(i * 4 + 4)]), words[i], .little);
|
||||||
} else {
|
|
||||||
var tmp: [4]u8 = undefined;
|
|
||||||
for (0..L) |i| {
|
|
||||||
tmp = word_to_bytes_le(words[i]);
|
|
||||||
bytes[i * 4] = tmp[0];
|
|
||||||
bytes[i * 4 + 1] = tmp[1];
|
|
||||||
bytes[i * 4 + 2] = tmp[2];
|
|
||||||
bytes[i * 4 + 3] = tmp[3];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn chacha20_deserialize(L: comptime_int, bytes: *const [L * 4]u8, words: *[L]u32) void {
|
fn chacha20_deserialize(L: comptime_int, bytes: *const [L * 4]u8, words: *[L]u32) void {
|
||||||
if (comptime @import("builtin").target.cpu.arch.endian() == .little) {
|
for (0..L) |i|
|
||||||
@memcpy(@as(*[L * 4]u8, @ptrCast(words)), bytes);
|
words[i] = std.mem.readInt(u32, @ptrCast(bytes[(i * 4)..(i * 4 + 4)]), .little);
|
||||||
} else {
|
|
||||||
for (0..L) |i| {
|
|
||||||
words[i] = bytes_to_word_le(@ptrCast(bytes[(i * 4)..(i * 4 + 4)]));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bytes_to_word_le(bytes: *const [4]u8) u32 {
|
fn bytes_to_word_le(bytes: *const [4]u8) u32 {
|
||||||
return (@as(u32, bytes[3]) << 24) | (@as(u32, bytes[2]) << 16) | (@as(u32, bytes[1]) << 8) | @as(u32, bytes[0]);
|
return std.mem.readInt(u32, bytes, .little);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn word_to_bytes_le(word: u32) [4]u8 {
|
fn word_to_bytes_le(word: u32) [4]u8 {
|
||||||
var bytes: [4]u8 = undefined;
|
var bytes: [4]u8 = undefined;
|
||||||
bytes[3] = @truncate(word >> 24);
|
std.mem.writeInt(u32, &bytes, word, .little);
|
||||||
bytes[2] = @truncate(word >> 16);
|
|
||||||
bytes[1] = @truncate(word >> 8);
|
|
||||||
bytes[0] = @truncate(word);
|
|
||||||
return bytes;
|
return bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
2
src/primitive/streamcipher/index.zig
Normal file
2
src/primitive/streamcipher/index.zig
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
pub const chacha20 = @import("chacha20.zig");
|
||||||
|
pub const salsa20 = @import("salsa20.zig");
|
||||||
@ -201,40 +201,22 @@ pub fn salsa20_block_function(ctx: *Salsa20Ctx) void {
|
|||||||
// ----------------------------------- LITTLE ENDIAN HELPERS ----------------------------------- //
|
// ----------------------------------- LITTLE ENDIAN HELPERS ----------------------------------- //
|
||||||
|
|
||||||
fn salsa20_serialize(L: comptime_int, words: *const [L]u32, bytes: *[L * 4]u8) void {
|
fn salsa20_serialize(L: comptime_int, words: *const [L]u32, bytes: *[L * 4]u8) void {
|
||||||
if (comptime @import("builtin").target.cpu.arch.endian() == .little) {
|
for (0..L) |i|
|
||||||
@memcpy(bytes, @as(*const [L * 4]u8, @ptrCast(words)));
|
std.mem.writeInt(u32, @ptrCast(bytes[(i * 4)..(i * 4 + 4)]), words[i], .little);
|
||||||
} else {
|
|
||||||
var tmp: [4]u8 = undefined;
|
|
||||||
for (0..L) |i| {
|
|
||||||
tmp = word_to_bytes_le(words[i]);
|
|
||||||
bytes[i * 4] = tmp[0];
|
|
||||||
bytes[i * 4 + 1] = tmp[1];
|
|
||||||
bytes[i * 4 + 2] = tmp[2];
|
|
||||||
bytes[i * 4 + 3] = tmp[3];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn salsa20_deserialize(L: comptime_int, bytes: *const [L * 4]u8, words: *[L]u32) void {
|
fn salsa20_deserialize(L: comptime_int, bytes: *const [L * 4]u8, words: *[L]u32) void {
|
||||||
if (comptime @import("builtin").target.cpu.arch.endian() == .little) {
|
for (0..L) |i|
|
||||||
@memcpy(@as(*[L * 4]u8, @ptrCast(words)), bytes);
|
words[i] = std.mem.readInt(u32, @ptrCast(bytes[(i * 4)..(i * 4 + 4)]), .little);
|
||||||
} else {
|
|
||||||
for (0..L) |i| {
|
|
||||||
words[i] = bytes_to_word_le(@ptrCast(bytes[(i * 4)..(i * 4 + 4)]));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bytes_to_word_le(bytes: *const [4]u8) u32 {
|
fn bytes_to_word_le(bytes: *const [4]u8) u32 {
|
||||||
return (@as(u32, bytes[3]) << 24) | (@as(u32, bytes[2]) << 16) | (@as(u32, bytes[1]) << 8) | @as(u32, bytes[0]);
|
return std.mem.readInt(u32, bytes, .little);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn word_to_bytes_le(word: u32) [4]u8 {
|
fn word_to_bytes_le(word: u32) [4]u8 {
|
||||||
var bytes: [4]u8 = undefined;
|
var bytes: [4]u8 = undefined;
|
||||||
bytes[3] = @truncate(word >> 24);
|
std.mem.writeInt(u32, &bytes, word, .little);
|
||||||
bytes[2] = @truncate(word >> 16);
|
|
||||||
bytes[1] = @truncate(word >> 8);
|
|
||||||
bytes[0] = @truncate(word);
|
|
||||||
return bytes;
|
return bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
22
src/root.zig
22
src/root.zig
@ -1,21 +1 @@
|
|||||||
const std = @import("std");
|
pub const primitive = @import("./primitive/index.zig");
|
||||||
const testing = std.testing;
|
|
||||||
|
|
||||||
const CryptoError = error{
|
|
||||||
InvalidBufferSize,
|
|
||||||
};
|
|
||||||
|
|
||||||
// rn just for build, later will be used by high-level API
|
|
||||||
pub const aes = @import("primitive/blockcipher/aes.zig");
|
|
||||||
pub const chacha20 = @import("primitive/streamcipher/chacha20.zig");
|
|
||||||
pub const salsa20 = @import("primitive/streamcipher/salsa20.zig");
|
|
||||||
pub const sha = @import("primitive/digest/sha.zig");
|
|
||||||
|
|
||||||
// Leave this for later, maybe make a separate ffi module
|
|
||||||
|
|
||||||
//export fn aes_128_encrypt_block_ffi(block_in: [*c]const u8, len_in: usize, block_out: [*c]u8, len_out: usize) !void {
|
|
||||||
// if (len_in != AES_128_BLOCK_SIZE or len_out != AES_128_BLOCK_SIZE)
|
|
||||||
// return CryptoError.InvalidBufferSize;
|
|
||||||
//
|
|
||||||
// aes_128_encrypt_block(block_in[0..AES_128_BLOCK_SIZE], block_out[0..AES_128_BLOCK_SIZE]);
|
|
||||||
//}
|
|
||||||
|
|||||||
14
src/test.zig
Normal file
14
src/test.zig
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
comptime {
|
||||||
|
_ = .{
|
||||||
|
@import("./primitive/blockcipher/aes.zig"),
|
||||||
|
@import("./primitive/blockcipher/des.zig"),
|
||||||
|
@import("./primitive/digest/sha_1.zig"),
|
||||||
|
@import("./primitive/digest/sha_2.zig"),
|
||||||
|
@import("./primitive/streamcipher/chacha20.zig"),
|
||||||
|
@import("./primitive/streamcipher/salsa20.zig"),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
test {
|
||||||
|
@import("std").testing.refAllDecls(@This());
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user