Пример #1
0
        /// <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 (Session session = _certContext.TokenContext.SlotContext.Slot.OpenSession(SessionType.ReadOnly))
                    using (var mechanism = new Mechanism(CKM.CKM_RSA_PKCS))
                    {
                        session.Verify(mechanism, _certContext.PubKeyHandle, pkcs1DigestInfo, signature, out bool isValid);
                        return(isValid);
                    }
            }
            else if (padding == RSASignaturePadding.Pss)
            {
                CkRsaPkcsPssParams pssMechanismParams = CreateCkRsaPkcsPssParams(hash, hashAlgorithm);
                if (pssMechanismParams == null)
                {
                    throw new NotSupportedException(string.Format("Algorithm {0} is not supported", hashAlgorithm.Name));
                }

                using (Session session = _certContext.TokenContext.SlotContext.Slot.OpenSession(SessionType.ReadOnly))
                    using (var mechanism = new Mechanism(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));
            }
        }
Пример #2
0
        /// <summary>
        /// Generates PKCS#7 signature of specified data
        /// </summary>
        /// <param name="data">Data to be signed</param>
        /// <param name="detached">Flag indicating whether detached signature should be produced</param>
        /// <param name="signingCertificate">Signing certificate</param>
        /// <param name="certPath">Certification path for signing certificate</param>
        /// <returns>DER encoded PKCS#7 signature of specified data</returns>
        public byte[] GenerateSignature(byte[] data, bool detached, BCX509.X509Certificate signingCertificate, ICollection <BCX509.X509Certificate> certPath)
        {
            if (this._disposed)
            {
                throw new ObjectDisposedException(this.GetType().FullName);
            }

            string  hashOid       = HashAlgorithmUtils.GetHashOid(_hashAlgorihtm);
            IDigest hashGenerator = HashAlgorithmUtils.GetHashGenerator(_hashAlgorihtm);

            // Compute hash of input data
            byte[] dataHash = ComputeDigest(hashGenerator, data);

            // Construct SignerInfo.signedAttrs
            Asn1EncodableVector signedAttributesVector = new Asn1EncodableVector();

            // Add PKCS#9 contentType signed attribute
            signedAttributesVector.Add(
                new Org.BouncyCastle.Asn1.Cms.Attribute(
                    attrType: new DerObjectIdentifier(OID.PKCS9AtContentType),
                    attrValues: new DerSet(new DerObjectIdentifier(OID.PKCS7IdData))));

            // Add PKCS#9 messageDigest signed attribute
            signedAttributesVector.Add(
                new Org.BouncyCastle.Asn1.Cms.Attribute(
                    attrType: new DerObjectIdentifier(OID.PKCS9AtMessageDigest),
                    attrValues: new DerSet(new DerOctetString(dataHash))));

            // Add PKCS#9 signingTime signed attribute
            signedAttributesVector.Add(
                new Org.BouncyCastle.Asn1.Cms.Attribute(
                    attrType: new DerObjectIdentifier(OID.PKCS9AtSigningTime),
                    attrValues: new DerSet(new Org.BouncyCastle.Asn1.Cms.Time(new DerUtcTime(DateTime.UtcNow)))));

            // Compute digest of SignerInfo.signedAttrs
            DerSet signedAttributes = new DerSet(signedAttributesVector);

            byte[] signedAttributesDigest = ComputeDigest(hashGenerator, signedAttributes.GetDerEncoded());

            // Sign digest of SignerInfo.signedAttrs with private key stored on PKCS#11 compatible device
            Asn1OctetString     digestSignature          = null;
            AlgorithmIdentifier digestSignatureAlgorithm = null;

            if (_signatureScheme == SignatureScheme.RSASSA_PKCS1_v1_5)
            {
                // Construct DigestInfo
                byte[] digestInfo = CreateDigestInfo(signedAttributesDigest, hashOid);

                // Sign DigestInfo with CKM_RSA_PKCS mechanism
                byte[] signature = null;

                using (Session session = _slot.OpenSession(SessionType.ReadOnly))
                    using (Mechanism mechanism = new Mechanism(CKM.CKM_RSA_PKCS))
                        signature = session.Sign(mechanism, _privateKeyHandle, digestInfo);

                // Construct SignerInfo.signature
                digestSignature = new DerOctetString(signature);

                // Construct SignerInfo.signatureAlgorithm
                digestSignatureAlgorithm = new AlgorithmIdentifier(
                    algorithm: new DerObjectIdentifier(OID.PKCS1RsaEncryption),
                    parameters: DerNull.Instance
                    );
            }
            else if (_signatureScheme == SignatureScheme.RSASSA_PSS)
            {
                // Construct parameters for CKM_RSA_PKCS_PSS mechanism
                CkRsaPkcsPssParams pssMechanismParams = CreateCkRsaPkcsPssParams(_hashAlgorihtm);

                // Sign digest with CKM_RSA_PKCS_PSS mechanism
                byte[] signature = null;

                using (Session session = _slot.OpenSession(SessionType.ReadOnly))
                    using (Mechanism mechanism = new Mechanism(CKM.CKM_RSA_PKCS_PSS, pssMechanismParams))
                        signature = session.Sign(mechanism, _privateKeyHandle, signedAttributesDigest);

                // Construct SignerInfo.signature
                digestSignature = new DerOctetString(signature);

                // Construct SignerInfo.signatureAlgorithm
                digestSignatureAlgorithm = new AlgorithmIdentifier(
                    algorithm: new DerObjectIdentifier(OID.PKCS1RsassaPss),
                    parameters: new Org.BouncyCastle.Asn1.Pkcs.RsassaPssParameters(
                        hashAlgorithm: new AlgorithmIdentifier(
                            algorithm: new DerObjectIdentifier(hashOid),
                            parameters: DerNull.Instance
                            ),
                        maskGenAlgorithm: new AlgorithmIdentifier(
                            algorithm: new DerObjectIdentifier(OID.PKCS1Mgf1),
                            parameters: new AlgorithmIdentifier(
                                algorithm: new DerObjectIdentifier(hashOid),
                                parameters: DerNull.Instance
                                )
                            ),
                        saltLength: new DerInteger(hashGenerator.GetDigestSize()),
                        trailerField: new DerInteger(1)
                        )
                    );
            }
            else
            {
                throw new NotSupportedException("Unsupported signature scheme");
            }

            // Construct SignerInfo
            SignerInfo signerInfo = new SignerInfo(
                sid: new SignerIdentifier(new IssuerAndSerialNumber(signingCertificate.IssuerDN, signingCertificate.SerialNumber)),
                digAlgorithm: new AlgorithmIdentifier(
                    algorithm: new DerObjectIdentifier(hashOid),
                    parameters: DerNull.Instance
                    ),
                authenticatedAttributes: signedAttributes,
                digEncryptionAlgorithm: digestSignatureAlgorithm,
                encryptedDigest: digestSignature,
                unauthenticatedAttributes: null
                );

            // Construct SignedData.digestAlgorithms
            Asn1EncodableVector digestAlgorithmsVector = new Asn1EncodableVector();

            digestAlgorithmsVector.Add(
                new AlgorithmIdentifier(
                    algorithm: new DerObjectIdentifier(hashOid),
                    parameters: DerNull.Instance));

            // Construct SignedData.encapContentInfo
            ContentInfo encapContentInfo = new ContentInfo(
                contentType: new DerObjectIdentifier(OID.PKCS7IdData),
                content: (detached) ? null : new DerOctetString(data));

            // Construct SignedData.certificates
            Asn1EncodableVector certificatesVector = new Asn1EncodableVector();

            foreach (BCX509.X509Certificate cert in certPath)
            {
                certificatesVector.Add(X509CertificateStructure.GetInstance(Asn1Object.FromByteArray(cert.GetEncoded())));
            }

            // Construct SignedData.signerInfos
            Asn1EncodableVector signerInfosVector = new Asn1EncodableVector();

            signerInfosVector.Add(signerInfo.ToAsn1Object());

            // Construct SignedData
            SignedData signedData = new SignedData(
                digestAlgorithms: new DerSet(digestAlgorithmsVector),
                contentInfo: encapContentInfo,
                certificates: new BerSet(certificatesVector),
                crls: null,
                signerInfos: new DerSet(signerInfosVector));

            // Construct top level ContentInfo
            ContentInfo contentInfo = new ContentInfo(
                contentType: new DerObjectIdentifier(OID.PKCS7IdSignedData),
                content: signedData);

            return(contentInfo.GetDerEncoded());
        }
Пример #3
0
        /// <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 (Session session = _certContext.TokenContext.SlotContext.Slot.OpenSession(SessionType.ReadOnly))
                    using (var mechanism = new Mechanism(CKM.CKM_RSA_PKCS))
                    {
                        if (_certContext.KeyUsageRequiresLogin)
                        {
                            return(session.Sign(mechanism, _certContext.PrivKeyHandle, pkcs1DigestInfo, PinProviderUtils.GetKeyPin(_certContext)));
                        }
                        else
                        {
                            return(session.Sign(mechanism, _certContext.PrivKeyHandle, pkcs1DigestInfo));
                        }
                    }
            }
            else if (padding == RSASignaturePadding.Pss)
            {
                CkRsaPkcsPssParams pssMechanismParams = CreateCkRsaPkcsPssParams(hash, hashAlgorithm);
                if (pssMechanismParams == null)
                {
                    throw new NotSupportedException(string.Format("Algorithm {0} is not supported", hashAlgorithm.Name));
                }

                using (Session session = _certContext.TokenContext.SlotContext.Slot.OpenSession(SessionType.ReadOnly))
                    using (var mechanism = new Mechanism(CKM.CKM_RSA_PKCS_PSS, pssMechanismParams))
                    {
                        if (_certContext.KeyUsageRequiresLogin)
                        {
                            return(session.Sign(mechanism, _certContext.PrivKeyHandle, hash, PinProviderUtils.GetKeyPin(_certContext)));
                        }
                        else
                        {
                            return(session.Sign(mechanism, _certContext.PrivKeyHandle, hash));
                        }
                    }
            }
            else
            {
                throw new NotSupportedException(string.Format("Padding {0} is not supported", padding));
            }
        }
Пример #4
0
        /// <summary>
        /// Creates parameters for CKM_RSA_PKCS_PSS mechanism
        /// </summary>
        /// <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 CkRsaPkcsPssParams CreateCkRsaPkcsPssParams(byte[] hash, HashAlgorithmName hashAlgorithm)
        {
            if (hash == null || hash.Length == 0)
            {
                throw new ArgumentNullException(nameof(hash));
            }

            CkRsaPkcsPssParams pssParams = null;

            if (hashAlgorithm == HashAlgorithmName.SHA1)
            {
                if (hash.Length != 20)
                {
                    throw new ArgumentException("Invalid lenght of hash value");
                }

                pssParams = new CkRsaPkcsPssParams(
                    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 = new CkRsaPkcsPssParams(
                    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 = new CkRsaPkcsPssParams(
                    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 = new CkRsaPkcsPssParams(
                    hashAlg: (ulong)CKM.CKM_SHA512,
                    mgf: (ulong)CKG.CKG_MGF1_SHA512,
                    len: (ulong)hash.Length
                    );
            }

            return(pssParams);
        }