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