/// <summary> /// Verifies that a digital signature is valid by determining the hash value in the signature using the specified hash algorithm and padding, and comparing it to the provided hash value /// </summary> /// <param name="hash">he hash value of the signed data</param> /// <param name="signature">The signature data to be verified</param> /// <param name="hashAlgorithm">The hash algorithm used to create the hash value</param> /// <param name="padding">The padding mode</param> /// <returns>True if the signature is valid, false otherwise</returns> public override bool VerifyHash(byte[] hash, byte[] signature, HashAlgorithmName hashAlgorithm, RSASignaturePadding padding) { if (hash == null || hash.Length == 0) { throw new ArgumentNullException(nameof(hash)); } if (signature == null || signature.Length == 0) { throw new ArgumentNullException(nameof(signature)); } if (hashAlgorithm == null) { throw new ArgumentNullException(nameof(hashAlgorithm)); } if (padding == null) { throw new ArgumentNullException(nameof(padding)); } if (padding == RSASignaturePadding.Pkcs1) { byte[] pkcs1DigestInfo = CreatePkcs1DigestInfo(hash, hashAlgorithm); if (pkcs1DigestInfo == null) { throw new NotSupportedException(string.Format("Algorithm {0} is not supported", hashAlgorithm)); } using (ISession session = _certContext.TokenContext.SlotContext.Slot.OpenSession(SessionType.ReadOnly)) using (IMechanism mechanism = session.Factories.MechanismFactory.Create(CKM.CKM_RSA_PKCS)) { session.Verify(mechanism, _certContext.PubKeyHandle, pkcs1DigestInfo, signature, out bool isValid); return(isValid); } } else if (padding == RSASignaturePadding.Pss) { IMechanismParamsFactory mechanismParamsFactory = _certContext.TokenContext.SlotContext.Slot.Factories.MechanismParamsFactory; ICkRsaPkcsPssParams pssMechanismParams = CreateCkRsaPkcsPssParams(mechanismParamsFactory, hash, hashAlgorithm); if (pssMechanismParams == null) { throw new NotSupportedException(string.Format("Algorithm {0} is not supported", hashAlgorithm.Name)); } using (ISession session = _certContext.TokenContext.SlotContext.Slot.OpenSession(SessionType.ReadOnly)) using (IMechanism mechanism = session.Factories.MechanismFactory.Create(CKM.CKM_RSA_PKCS_PSS, pssMechanismParams)) { session.Verify(mechanism, _certContext.PubKeyHandle, hash, signature, out bool isValid); return(isValid); } } else { throw new NotSupportedException(string.Format("Padding {0} is not supported", padding)); } }
public override byte[] SignHash(byte[] hash, HashAlgorithmName hashAlgorithm, RSASignaturePadding padding) { if (hash == null || hash.Length == 0) { throw new ArgumentNullException(nameof(hash)); } if (hashAlgorithm == null) { throw new ArgumentNullException(nameof(hashAlgorithm)); } if (padding == null) { throw new ArgumentNullException(nameof(padding)); } if (padding == RSASignaturePadding.Pkcs1) { byte[] pkcs1DigestInfo = CreatePkcs1DigestInfo(hash, hashAlgorithm); if (pkcs1DigestInfo == null) { throw new NotSupportedException(string.Format("Algorithm {0} is not supported", hashAlgorithm.Name)); } using (IMechanism mechanism = _session.Factories.MechanismFactory.Create(CKM.CKM_RSA_PKCS)) { return(_session.Sign(mechanism, _privateKeyHandle, pkcs1DigestInfo)); } } else if (padding == RSASignaturePadding.Pss) { IMechanismParamsFactory mechanismParamsFactory = _slot.Factories.MechanismParamsFactory; ICkRsaPkcsPssParams pssMechanismParams = CreateCkRsaPkcsPssParams(mechanismParamsFactory, hash, hashAlgorithm); if (pssMechanismParams == null) { throw new NotSupportedException(string.Format("Algorithm {0} is not supported", hashAlgorithm.Name)); } using (IMechanism mechanism = _session.Factories.MechanismFactory.Create(CKM.CKM_RSA_PKCS_PSS, pssMechanismParams)) { return(_session.Sign(mechanism, _privateKeyHandle, hash)); } } else { throw new NotSupportedException(string.Format("Padding {0} is not supported", padding)); } }
/// <summary> /// Computes the signature for the specified hash value by encrypting it with the private key using the specified padding /// </summary> /// <param name="hash">The hash value of the data to be signed</param> /// <param name="hashAlgorithm">The hash algorithm used to create the hash value of the data</param> /// <param name="padding">The padding</param> /// <returns>The RSA signature for the specified hash value</returns> public override byte[] SignHash(byte[] hash, HashAlgorithmName hashAlgorithm, RSASignaturePadding padding) { if (hash == null || hash.Length == 0) { throw new ArgumentNullException(nameof(hash)); } if (hashAlgorithm == null) { throw new ArgumentNullException(nameof(hashAlgorithm)); } if (padding == null) { throw new ArgumentNullException(nameof(padding)); } if (padding == RSASignaturePadding.Pkcs1) { byte[] pkcs1DigestInfo = CreatePkcs1DigestInfo(hash, hashAlgorithm); if (pkcs1DigestInfo == null) { throw new NotSupportedException(string.Format("Algorithm {0} is not supported", hashAlgorithm.Name)); } using (ISession session = _certContext.TokenContext.SlotContext.Slot.OpenSession(SessionType.ReadOnly)) using (IMechanism mechanism = session.Factories.MechanismFactory.Create(CKM.CKM_RSA_PKCS)) { if (_certContext.KeyUsageRequiresLogin) { return(session.Sign(mechanism, _certContext.PrivKeyHandle, PinProviderUtils.GetKeyPin(_certContext), pkcs1DigestInfo)); } else { return(session.Sign(mechanism, _certContext.PrivKeyHandle, pkcs1DigestInfo)); } } } else if (padding == RSASignaturePadding.Pss) { IMechanismParamsFactory mechanismParamsFactory = _certContext.TokenContext.SlotContext.Slot.Factories.MechanismParamsFactory; ICkRsaPkcsPssParams pssMechanismParams = CreateCkRsaPkcsPssParams(mechanismParamsFactory, hash, hashAlgorithm); if (pssMechanismParams == null) { throw new NotSupportedException(string.Format("Algorithm {0} is not supported", hashAlgorithm.Name)); } using (ISession session = _certContext.TokenContext.SlotContext.Slot.OpenSession(SessionType.ReadOnly)) using (IMechanism mechanism = session.Factories.MechanismFactory.Create(CKM.CKM_RSA_PKCS_PSS, pssMechanismParams)) { if (_certContext.KeyUsageRequiresLogin) { return(session.Sign(mechanism, _certContext.PrivKeyHandle, PinProviderUtils.GetKeyPin(_certContext), hash)); } else { return(session.Sign(mechanism, _certContext.PrivKeyHandle, hash)); } } } else { throw new NotSupportedException(string.Format("Padding {0} is not supported", padding)); } }
/// <summary> /// Creates parameters for CKM_RSA_PKCS_PSS mechanism /// </summary> /// <param name="mechanismParamsFactory">Factory for creation of IMechanismParams instances</param> /// <param name="hash">Hash value</param> /// <param name="hashAlgorithm">Hash algorithm</param> /// <returns>Parameters for CKM_RSA_PKCS_PSS mechanism or null</returns> private static ICkRsaPkcsPssParams CreateCkRsaPkcsPssParams(IMechanismParamsFactory mechanismParamsFactory, byte[] hash, HashAlgorithmName hashAlgorithm) { if (hash == null || hash.Length == 0) { throw new ArgumentNullException(nameof(hash)); } ICkRsaPkcsPssParams pssParams = null; if (hashAlgorithm == HashAlgorithmName.SHA1) { if (hash.Length != 20) { throw new ArgumentException("Invalid lenght of hash value"); } pssParams = mechanismParamsFactory.CreateCkRsaPkcsPssParams( hashAlg: (ulong)CKM.CKM_SHA_1, mgf: (ulong)CKG.CKG_MGF1_SHA1, len: (ulong)hash.Length ); } else if (hashAlgorithm == HashAlgorithmName.SHA256) { if (hash.Length != 32) { throw new ArgumentException("Invalid lenght of hash value"); } pssParams = mechanismParamsFactory.CreateCkRsaPkcsPssParams( hashAlg: (ulong)CKM.CKM_SHA256, mgf: (ulong)CKG.CKG_MGF1_SHA256, len: (ulong)hash.Length ); } else if (hashAlgorithm == HashAlgorithmName.SHA384) { if (hash.Length != 48) { throw new ArgumentException("Invalid lenght of hash value"); } pssParams = mechanismParamsFactory.CreateCkRsaPkcsPssParams( hashAlg: (ulong)CKM.CKM_SHA384, mgf: (ulong)CKG.CKG_MGF1_SHA384, len: (ulong)hash.Length ); } else if (hashAlgorithm == HashAlgorithmName.SHA512) { if (hash.Length != 64) { throw new ArgumentException("Invalid lenght of hash value"); } pssParams = mechanismParamsFactory.CreateCkRsaPkcsPssParams( hashAlg: (ulong)CKM.CKM_SHA512, mgf: (ulong)CKG.CKG_MGF1_SHA512, len: (ulong)hash.Length ); } return(pssParams); }