Livt packages
Livt.Crypto
Version 1.0.5
Fixed-size cryptographic components for Livt, including AES, ChaCha20, SHA, MACs, and key derivation.
Published files (69)
tests/kdf/HkdfSha256Test.lvt
namespace Livt.Crypto.Tests.Kdf
using Livt.Crypto.Kdf
// Tests for HkdfSha256 (RFC 5869 / HMAC-SHA-256).
@Test component HkdfSha256Test
{
hkdf: HkdfSha256
new()
{
this.hkdf = new HkdfSha256()
}
// RFC 5869 Test Case 1
// Hash = SHA-256
// IKM = 0x0b * 22
// salt = 0x000102...0x0c (13 bytes, zero-padded to 32 for SetKey)
// info = 0xf0f1...0xf9 (10 bytes)
// L = 42
//
// PRK = HMAC-SHA256(salt, IKM):
// 0777093 62c2e32df0ddc3f0dc47bba6390b6c73bb50f9c3122ec844ad7c2b3e5
//
// OKM (42 bytes) = T(1) || T(2)[0..9]:
// 3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf
// 34007208d5b887185865
//
// Inner SHA-256 block sizes (k_ipad prefix + message):
// Extract: 64 + 22 = 86 bytes → ikmBlock pads with be64(688 = 0x2b0)
// ExpandT1: 64 + 11 = 75 bytes → t1Block pads with be64(600 = 0x258)
// ExpandT2: 64 + 43 = 107 bytes → t2Block pads with be64(856 = 0x358)
@Test fn TestRfc5869Tc1()
{
// --- Extract ---
var salt: byte[32] = [
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
var ikmBlock: byte[64] = [
0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x80, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xb0]
var prk: byte[32] = this.hkdf.Extract(salt, ikmBlock)
assert prk[0] == 0x07; assert prk[1] == 0x77; assert prk[2] == 0x09; assert prk[3] == 0x36
assert prk[4] == 0x2c; assert prk[5] == 0x2e; assert prk[6] == 0x32; assert prk[7] == 0xdf
assert prk[8] == 0x0d; assert prk[9] == 0xdc; assert prk[10] == 0x3f; assert prk[11] == 0x0d
assert prk[12] == 0xc4; assert prk[13] == 0x7b; assert prk[14] == 0xba; assert prk[15] == 0x63
assert prk[16] == 0x90; assert prk[17] == 0xb6; assert prk[18] == 0xc7; assert prk[19] == 0x3b
assert prk[20] == 0xb5; assert prk[21] == 0x0f; assert prk[22] == 0x9c; assert prk[23] == 0x31
assert prk[24] == 0x22; assert prk[25] == 0xec; assert prk[26] == 0x84; assert prk[27] == 0x4a
assert prk[28] == 0xd7; assert prk[29] == 0xc2; assert prk[30] == 0xb3; assert prk[31] == 0xe5
// --- ExpandT1: T(1) = HMAC-SHA256(PRK, info || 0x01 || padding) ---
// info (10 B) || 0x01 || 0x80 || 0x00*44 || be64(600) = 64 bytes
var t1Block: byte[64] = [
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
0xf8, 0xf9, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x58]
var t1: byte[32] = this.hkdf.ExpandT1(prk, t1Block)
// T(1) = OKM bytes 0..31
assert t1[0] == 0x3c; assert t1[1] == 0xb2; assert t1[2] == 0x5f; assert t1[3] == 0x25
assert t1[4] == 0xfa; assert t1[5] == 0xac; assert t1[6] == 0xd5; assert t1[7] == 0x7a
assert t1[8] == 0x90; assert t1[9] == 0x43; assert t1[10] == 0x4f; assert t1[11] == 0x64
assert t1[12] == 0xd0; assert t1[13] == 0x36; assert t1[14] == 0x2f; assert t1[15] == 0x2a
assert t1[16] == 0x2d; assert t1[17] == 0x2d; assert t1[18] == 0x0a; assert t1[19] == 0x90
assert t1[20] == 0xcf; assert t1[21] == 0x1a; assert t1[22] == 0x5a; assert t1[23] == 0x4c
assert t1[24] == 0x5d; assert t1[25] == 0xb0; assert t1[26] == 0x2d; assert t1[27] == 0x56
assert t1[28] == 0xec; assert t1[29] == 0xc4; assert t1[30] == 0xc5; assert t1[31] == 0xbf
// --- ExpandT2: T(2) = HMAC-SHA256(PRK, T(1) || info || 0x02 || padding) ---
// T(1)(32 B) || info(10 B) || 0x02 || 0x80 || 0x00*12 || be64(856) = 64 bytes
var t2Block: byte[64] = [
0x3c, 0xb2, 0x5f, 0x25, 0xfa, 0xac, 0xd5, 0x7a,
0x90, 0x43, 0x4f, 0x64, 0xd0, 0x36, 0x2f, 0x2a,
0x2d, 0x2d, 0x0a, 0x90, 0xcf, 0x1a, 0x5a, 0x4c,
0x5d, 0xb0, 0x2d, 0x56, 0xec, 0xc4, 0xc5, 0xbf,
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
0xf8, 0xf9, 0x02, 0x80, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x58]
var t2: byte[32] = this.hkdf.ExpandTN(prk, t2Block)
// OKM bytes 32..41 = T(2)[0..9]
assert t2[0] == 0x34; assert t2[1] == 0x00; assert t2[2] == 0x72; assert t2[3] == 0x08
assert t2[4] == 0xd5; assert t2[5] == 0xb8; assert t2[6] == 0x87; assert t2[7] == 0x18
assert t2[8] == 0x58; assert t2[9] == 0x65
}
// RFC 5869 Test Case 3
// Hash = SHA-256
// IKM = 0x0b * 22
// salt = not provided (use HashLen = 32 zero bytes per RFC 5869 §2.2)
// info = not provided (empty)
// L = 42
//
// PRK = HMAC-SHA256(0x00*32, IKM):
// 19ef24a32c717b167f33a91d6f648bdf96596776afdb6377ac434c1c293ccb04
//
// OKM (42 bytes) = T(1) || T(2)[0..9]:
// 8da4e775a563c18f715f802a063c5a31b8a11f5c5ee1879ec3454e5f3c738d2d
// 9d201395faa4b61a96c8
//
// Inner SHA-256 block sizes:
// Extract: 64 + 22 = 86 bytes → ikmBlock pads with be64(688 = 0x2b0) [same as TC1]
// ExpandT1: 64 + 1 = 65 bytes → t1Block pads with be64(520 = 0x208)
// ExpandT2: 64 + 33 = 97 bytes → t2Block pads with be64(776 = 0x308)
@Test fn TestRfc5869Tc3()
{
// --- Extract (no salt = 32 zero bytes) ---
var salt: byte[32] = [
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
var ikmBlock: byte[64] = [
0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x80, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xb0]
var prk: byte[32] = this.hkdf.Extract(salt, ikmBlock)
assert prk[0] == 0x19; assert prk[1] == 0xef; assert prk[2] == 0x24; assert prk[3] == 0xa3
assert prk[4] == 0x2c; assert prk[5] == 0x71; assert prk[6] == 0x7b; assert prk[7] == 0x16
assert prk[8] == 0x7f; assert prk[9] == 0x33; assert prk[10] == 0xa9; assert prk[11] == 0x1d
assert prk[12] == 0x6f; assert prk[13] == 0x64; assert prk[14] == 0x8b; assert prk[15] == 0xdf
assert prk[16] == 0x96; assert prk[17] == 0x59; assert prk[18] == 0x67; assert prk[19] == 0x76
assert prk[20] == 0xaf; assert prk[21] == 0xdb; assert prk[22] == 0x63; assert prk[23] == 0x77
assert prk[24] == 0xac; assert prk[25] == 0x43; assert prk[26] == 0x4c; assert prk[27] == 0x1c
assert prk[28] == 0x29; assert prk[29] == 0x3c; assert prk[30] == 0xcb; assert prk[31] == 0x04
// --- ExpandT1: T(1) = HMAC-SHA256(PRK, 0x01 || padding) (no info) ---
// 0x01 || 0x80 || 0x00*54 || be64(520) = 64 bytes
var t1Block: byte[64] = [
0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x08]
var t1: byte[32] = this.hkdf.ExpandT1(prk, t1Block)
// T(1) = OKM bytes 0..31
assert t1[0] == 0x8d; assert t1[1] == 0xa4; assert t1[2] == 0xe7; assert t1[3] == 0x75
assert t1[4] == 0xa5; assert t1[5] == 0x63; assert t1[6] == 0xc1; assert t1[7] == 0x8f
assert t1[8] == 0x71; assert t1[9] == 0x5f; assert t1[10] == 0x80; assert t1[11] == 0x2a
assert t1[12] == 0x06; assert t1[13] == 0x3c; assert t1[14] == 0x5a; assert t1[15] == 0x31
assert t1[16] == 0xb8; assert t1[17] == 0xa1; assert t1[18] == 0x1f; assert t1[19] == 0x5c
assert t1[20] == 0x5e; assert t1[21] == 0xe1; assert t1[22] == 0x87; assert t1[23] == 0x9e
assert t1[24] == 0xc3; assert t1[25] == 0x45; assert t1[26] == 0x4e; assert t1[27] == 0x5f
assert t1[28] == 0x3c; assert t1[29] == 0x73; assert t1[30] == 0x8d; assert t1[31] == 0x2d
// --- ExpandT2: T(2) = HMAC-SHA256(PRK, T(1) || 0x02 || padding) (no info) ---
// T(1)(32 B) || 0x02 || 0x80 || 0x00*22 || be64(776) = 64 bytes
var t2Block: byte[64] = [
0x8d, 0xa4, 0xe7, 0x75, 0xa5, 0x63, 0xc1, 0x8f,
0x71, 0x5f, 0x80, 0x2a, 0x06, 0x3c, 0x5a, 0x31,
0xb8, 0xa1, 0x1f, 0x5c, 0x5e, 0xe1, 0x87, 0x9e,
0xc3, 0x45, 0x4e, 0x5f, 0x3c, 0x73, 0x8d, 0x2d,
0x02, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x08]
var t2: byte[32] = this.hkdf.ExpandTN(prk, t2Block)
// OKM bytes 32..41 = T(2)[0..9]
assert t2[0] == 0x9d; assert t2[1] == 0x20; assert t2[2] == 0x13; assert t2[3] == 0x95
assert t2[4] == 0xfa; assert t2[5] == 0xa4; assert t2[6] == 0xb6; assert t2[7] == 0x1a
assert t2[8] == 0x96; assert t2[9] == 0xc8
}
}