Skip to content

Commit 9c68ea2

Browse files
DennisDyalloclaude
andcommitted
refactor(core): dedupe ARKG HKDF — delegate to shared HkdfUtilities
Removes the private HkdfSha256 method from ArkgPrimitivesOpenSsl that existed solely as a workaround because HkdfUtilities lived in the wrong assembly (Yubico.YubiKey, unreachable from Core). Now that HkdfUtilities is in Yubico.Core, ARKG can call the shared canonical implementation. 44 lines of duplicated cryptographic code removed. ARKG KAT vectors verify byte-for-byte equivalence with the previous local copy. The .ToArray() calls at lines 271 + 291 are forced by downstream code expecting byte[] (mk fed to HMACSHA256 ctor, shared returned as byte[]). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 786c5e9 commit 9c68ea2

1 file changed

Lines changed: 2 additions & 52 deletions

File tree

Yubico.Core/src/Yubico/Core/Cryptography/ArkgPrimitivesOpenSsl.cs

Lines changed: 2 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,7 @@ private static byte[] BlBlindPublicKey(byte[] pkBl, BigInteger tau)
268268
Encoding.ASCII.GetBytes("ARKG-KEM-HMAC-mac."),
269269
dstAug,
270270
ctx);
271-
byte[] mk = HkdfSha256(kPrime, salt: Array.Empty<byte>(), info: macInfo, length: 32);
271+
byte[] mk = HkdfUtilities.DeriveKey(kPrime, salt: ReadOnlySpan<byte>.Empty, contextInfo: macInfo, length: 32).ToArray();
272272

273273
byte[] tag;
274274
try
@@ -288,7 +288,7 @@ private static byte[] BlBlindPublicKey(byte[] pkBl, BigInteger tau)
288288
Encoding.ASCII.GetBytes("ARKG-KEM-HMAC-shared."),
289289
dstAug,
290290
ctx);
291-
byte[] shared = HkdfSha256(kPrime, salt: Array.Empty<byte>(), info: sharedInfo, length: kPrime.Length);
291+
byte[] shared = HkdfUtilities.DeriveKey(kPrime, salt: ReadOnlySpan<byte>.Empty, contextInfo: sharedInfo, length: kPrime.Length).ToArray();
292292
CryptographicOperations.ZeroMemory(kPrime);
293293

294294
// Ciphertext = MAC tag || ephemeral public key.
@@ -412,56 +412,6 @@ private static byte[] ExpandMessageXmd(byte[] msg, byte[] dst, int lenInBytes)
412412
return result;
413413
}
414414

415-
// ---------------------------------------------------------------------
416-
// HKDF-SHA256 (RFC 5869) — local copy because Yubico.Core can't depend
417-
// on Yubico.YubiKey's HkdfUtilities.
418-
// ---------------------------------------------------------------------
419-
420-
private static byte[] HkdfSha256(byte[] ikm, byte[] salt, byte[] info, int length)
421-
{
422-
const int HashLen = 32;
423-
byte[] effectiveSalt = (salt == null || salt.Length == 0) ? new byte[HashLen] : salt;
424-
425-
byte[] prk;
426-
using (HMACSHA256 hmac = new HMACSHA256(effectiveSalt))
427-
{
428-
prk = hmac.ComputeHash(ikm);
429-
}
430-
431-
try
432-
{
433-
byte[] okm = new byte[length];
434-
int blocks = (length + HashLen - 1) / HashLen;
435-
byte[] previous = Array.Empty<byte>();
436-
437-
using HMACSHA256 expandHmac = new HMACSHA256(prk);
438-
for (int i = 1; i <= blocks; i++)
439-
{
440-
byte[] input = new byte[previous.Length + (info?.Length ?? 0) + 1];
441-
Buffer.BlockCopy(previous, 0, input, 0, previous.Length);
442-
if (info != null)
443-
{
444-
Buffer.BlockCopy(info, 0, input, previous.Length, info.Length);
445-
}
446-
447-
input[^1] = (byte)i;
448-
449-
expandHmac.Initialize();
450-
byte[] block = expandHmac.ComputeHash(input);
451-
int off = (i - 1) * HashLen;
452-
int copy = Math.Min(HashLen, length - off);
453-
Buffer.BlockCopy(block, 0, okm, off, copy);
454-
previous = block;
455-
}
456-
457-
return okm;
458-
}
459-
finally
460-
{
461-
CryptographicOperations.ZeroMemory(prk);
462-
}
463-
}
464-
465415
// ---------------------------------------------------------------------
466416
// Conversion helpers
467417
// ---------------------------------------------------------------------

0 commit comments

Comments
 (0)