/// <summary> /// Uses the procedure defined in RFC 4226 section 7.5 to derive a key from the master key /// </summary> /// <param name="masterKey">The master key from which to derive a device specific key</param> /// <param name="publicIdentifier">The public identifier that is unique to the authenticating device</param> /// <param name="mode">The hash mode to use. This will determine the resulting key lenght. The default is sha-1 (as per the RFC) which is 20 bytes</param> /// <returns>Derived key</returns> public static byte[] DeriveKeyFromMaster(IKeyProvider masterKey, byte[] publicIdentifier, OtpHashMode mode = OtpHashMode.Sha1) { if (masterKey == null) { throw new ArgumentNullException("masterKey"); } return(masterKey.ComputeHmac(mode, publicIdentifier)); }
/// <summary> /// Helper method that calculates OTPs /// </summary> protected internal long CalculateOtp(byte[] data, OtpHashMode mode) { var hmacComputedHash = SecretKey.ComputeHmac(mode, data); // The RFC has a hard coded index 19 in this value. // This is the same thing but also accomodates SHA256 and SHA512 // hmacComputedHash[19] => hmacComputedHash[hmacComputedHash.Length - 1] var offset = hmacComputedHash[hmacComputedHash.Length - 1] & 0x0F; return((hmacComputedHash[offset] & 0x7f) << 24 | (hmacComputedHash[offset + 1] & 0xff) << 16 | (hmacComputedHash[offset + 2] & 0xff) << 8 | (hmacComputedHash[offset + 3] & 0xff) % 1000000); }
/// <summary> /// Uses the procedure defined in RFC 4226 section 7.5 to derive a key from the master key /// </summary> /// <param name="masterKey">The master key from which to derive a device specific key</param> /// <param name="publicIdentifier">The public identifier that is unique to the authenticating device</param> /// <param name="mode">The hash mode to use. This will determine the resulting key lenght. The default is sha-1 (as per the RFC) which is 20 bytes</param> /// <returns>Derived key</returns> public static byte[] DeriveKeyFromMaster(IKeyProvider masterKey, byte[] publicIdentifier, OtpHashMode mode = OtpHashMode.Sha1) { if (masterKey == null) throw new ArgumentNullException("masterKey"); return masterKey.ComputeHmac(mode, publicIdentifier); }