from std/secure import KeyDerivation;
from std/string/base64 import decode, encode;
from test/more import *;
let ikm1 := decode("CwsLCwsLCwsLCwsLCwsLCwsLCwsLCw==");
let salt1 := decode("AAECAwQFBgcICQoLDA==");
let info1 := decode("8PHy8/T19vf4+Q==");
let okm1 := "PLJfJfqs1XqQQ09k0DYvKi0tCpDPGlpMXbAtVuzExb80AHII1biHGFhl";
let ikm2 := decode(
"AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygp"
_ "KissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZHSElKS0xNTk8=",
);
let salt2 := decode(
"YGFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6e3x9fn+AgYKDhIWGh4iJ"
_ "iouMjY6PkJGSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmqq6ytrq8=",
);
let info2 := decode(
"sLGys7S1tre4ubq7vL2+v8DBwsPExcbHyMnKy8zNzs/Q0dLT1NXW19jZ"
_ "2tvc3d7f4OHi4+Tl5ufo6err7O3u7/Dx8vP09fb3+Pn6+/z9/v8=",
);
let okm2 := "sR45jcgDJ6HI5/eMWWpJNE8BLtotTvrYoFDMTBmvqXxZBFqZyseC"
_ "cnHLQcZeWQ4J2jJ1YAwvCbg2d5OprKPbccwwxYF57D6HwUwB1cHzQ08dhw==";
let okm3 := "jaTndaVjwY9xX4AqBjxaMbihH1xe4Yeew0VOXzxzjS2dIBOV+qS2GpbI";
let derived1 := KeyDerivation.hkdf_sha256( ikm1, 42, salt1, info1 );
is( typeof derived1, "BinaryString", "hkdf returns BinaryString" );
is( length derived1, 42, "hkdf returns requested length" );
is( encode(derived1), okm1, "RFC 5869 test case 1" );
is(
encode( KeyDerivation.hkdf_sha256( ikm2, 82, salt2, info2 ) ),
okm2,
"RFC 5869 test case 2",
);
is(
encode( KeyDerivation.hkdf_sha256( ikm1, 42, null, null ) ),
okm3,
"RFC 5869 test case 3",
);
is(
KeyDerivation.hkdf_sha256( ikm1, 0, salt1, info1 ),
decode(""),
"zero-length hkdf returns empty BinaryString",
);
is(
KeyDerivation.hkdf_sha256( ikm1, 42, null, null ),
KeyDerivation.hkdf_sha256( ikm1, 42, decode(""), decode("") ),
"null salt and info match explicit empty values",
);
let async_derived := await {
KeyDerivation.hkdf_sha256_async( ikm1, 42, salt1, info1 );
};
is( encode(async_derived), okm1, "hkdf async result matches sync" );
like(
exception( function () {
KeyDerivation.hkdf_sha256( "not binary", 32 );
} ),
/TypeException.*BinaryString/,
"hkdf rejects String input key material",
);
like(
exception( function () {
KeyDerivation.hkdf_sha256( ikm1, 1.5 );
} ),
/length between 0 and 8160/,
"hkdf rejects fractional length",
);
like(
exception( function () {
KeyDerivation.hkdf_sha256( ikm1, 8161 );
} ),
/length between 0 and 8160/,
"hkdf rejects too-long output",
);
like(
exception( function () {
KeyDerivation.hkdf_sha256( ikm1, 32, "salt" );
} ),
/BinaryString salt/,
"hkdf rejects String salt",
);
like(
exception( function () {
KeyDerivation.hkdf_sha256( ikm1, 32, null, "info" );
} ),
/BinaryString info/,
"hkdf rejects String info",
);
done_testing();