示例#1
0
        void signContent(MessageSigner messageSigner, Byte[] content)
        {
            hashAlgId   = new AlgorithmIdentifier(messageSigner.HashingAlgorithm.ToOid(), new Byte[0]);
            pubKeyAlgId = new AlgorithmIdentifier(messageSigner.PublicKeyAlgorithm, new Byte[0]);
            prepareSigning(content);
            SignedContentBlob signedBlob;

            if (_authAttributes.Any())
            {
                // auth attributes are encoded as IMPLICIT (OPTIONAL), but RFC2315 §9.3 requires signature computation for SET
                var attrBytes = _authAttributes.Encode();
                attrBytes[0] = 0x31;
                signedBlob   = new SignedContentBlob(attrBytes, ContentBlobType.ToBeSignedBlob);
            }
            else
            {
                if (content == null)
                {
                    throw new ArgumentException("'content' parameter cannot be null if no authenticated attributes present.");
                }
                signedBlob = new SignedContentBlob(content, ContentBlobType.ToBeSignedBlob);
            }
            signerCert = new PkcsSubjectIdentifier(messageSigner.SignerCertificate, SubjectIdentifier);
            signedBlob.Sign(messageSigner);
            hashValue = signedBlob.Signature.Value;
        }
        X509Certificate2 build(X509Certificate2 signer)
        {
            MessageSigner signerInfo = signer == null
                ? new MessageSigner(PrivateKeyInfo, HashingAlgorithm)
                : new MessageSigner(signer, HashingAlgorithm);

            signerInfo.PaddingScheme = AlternateSignatureFormat
                ? SignaturePadding.PSS
                : SignaturePadding.PKCS1;
            // initialize from v3 version
            var rawData = new List <Byte>(_versionBytes);

            // serial number
            rawData.AddRange(Asn1Utils.Encode(serialNumber, (Byte)Asn1Type.INTEGER));
            // algorithm identifier
            rawData.AddRange(signerInfo.GetAlgorithmIdentifier(AlternateSignatureFormat).RawData);
            // issuer
            rawData.AddRange(signer == null
                ? SubjectName.RawData
                : signer.SubjectName.RawData);
            // NotBefore and NotAfter
            List <Byte> date = Asn1Utils.EncodeDateTime(NotBefore).ToList();

            date.AddRange(Asn1Utils.EncodeDateTime(NotAfter));
            rawData.AddRange(Asn1Utils.Encode(date.ToArray(), 48));
            // subject
            rawData.AddRange(SubjectName.RawData);
            rawData.AddRange(PrivateKeyInfo.GetPublicKey().Encode());
            rawData.AddRange(Asn1Utils.Encode(finalExtensions.Encode(), 0xa3));
            var blob = new SignedContentBlob(Asn1Utils.Encode(rawData.ToArray(), 48), ContentBlobType.ToBeSignedBlob);

            blob.Sign(signerInfo);
            return(new X509Certificate2(blob.Encode()));
        }
        /// <summary>
        /// Displays an X.509 certificate dump.
        /// </summary>
        /// <returns>Formatted string.</returns>
        public static String Format(this X509Certificate2 cert)
        {
            if (cert == null)
            {
                return(String.Empty);
            }

            var    blob     = new SignedContentBlob(cert.RawData, ContentBlobType.SignedBlob);
            String sigValue = AsnFormatter.BinaryToString(blob.Signature.Value.Reverse().ToArray(), EncodingType.HexAddress)
                              .Replace(Environment.NewLine, Environment.NewLine + "    ");
            var sb = new StringBuilder();


            sb.Append($@"X509 Certificate:
Version: {cert.Version} (0x{cert.Version - 1:x})
Serial Number: {cert.SerialNumber}

{blob.SignatureAlgorithm}
Issuer:
    {cert.IssuerName.FormatReverse(true).Replace(Environment.NewLine, Environment.NewLine + "    ")}
  Name Hash(md5)    : {getNameHash(cert.IssuerName, MD5.Create())}
  Name Hash(sha1)   : {getNameHash(cert.IssuerName, SHA1.Create())}
  Name Hash(sha256) : {getNameHash(cert.IssuerName, SHA256.Create())}

Valid From: {cert.NotBefore}
Valid To  : {cert.NotAfter}

Subject:
    {cert.SubjectName.FormatReverse(true).Replace(Environment.NewLine, Environment.NewLine + "    ")}
  Name Hash(md5)    : {getNameHash(cert.SubjectName, MD5.Create())}
  Name Hash(sha1)   : {getNameHash(cert.SubjectName, SHA1.Create())}
  Name Hash(sha256) : {getNameHash(cert.SubjectName, SHA256.Create())}

{cert.PublicKey.Format().TrimEnd()}

Certificate Extensions: {cert.Extensions.Count}
{cert.Extensions.Format()}

{blob.SignatureAlgorithm.ToString().TrimEnd()}
Signature: UnusedBits={blob.Signature.UnusedBits}
    {sigValue}
");
            sb.AppendLine(cert.Issuer.Equals(cert.Subject, StringComparison.InvariantCultureIgnoreCase)
                ? "Root Certificate: Subject matches Issuer"
                : "Non-root Certificate");
            sb.AppendLine($"Key Id Hash(sha1)       : {getHashData(cert.PublicKey.Encode(), SHA1.Create())}");
            sb.AppendLine($"Key Id Hash(rfc-md5)    : {getHashData(cert.PublicKey.EncodedKeyValue.RawData, MD5.Create())}");
            sb.AppendLine($"Key Id Hash(rfc-sha1)   : {getHashData(cert.PublicKey.EncodedKeyValue.RawData, SHA1.Create())}");
            sb.AppendLine($"Key Id Hash(rfc-sha256) : {getHashData(cert.PublicKey.EncodedKeyValue.RawData, SHA256.Create())}");
            sb.AppendLine($"Key Id Hash(pin-sha256-b64) : {getKeyPinHash(cert.PublicKey, SHA256.Create())}");
            sb.AppendLine($"Key Id Hash(pin-sha256-hex) : {getHashData(cert.PublicKey.Encode(), SHA256.Create())}");
            sb.AppendLine($"Cert Hash(md5)    : {getCertHash(cert, MD5.Create())}");
            sb.AppendLine($"Cert Hash(sha1)   : {getCertHash(cert, SHA1.Create())}");
            sb.AppendLine($"Cert Hash(sha256) : {getCertHash(cert, SHA256.Create())}");
            sb.AppendLine($"Signature Hash    : {getHashData(blob.GetRawSignature(), SHA1.Create())}");
            return(sb.ToString());
        }
示例#4
0
        ///  <summary>
        ///		Verifies whether the specified certificate is an issuer of this CRL by verifying CRL signature
        ///		against specified certificate's public key.
        ///  </summary>
        ///  <param name="issuer">
        ///		A potential issuer's certificate.
        /// </param>
        /// <param name="strict">
        ///		Specifies whether to perform CRL issuer and certificate's subject name binary comparison.
        /// </param>
        /// <exception cref="CryptographicException">
        ///         The data is invalid.
        ///  </exception>
        /// <exception cref="UninitializedObjectException">An object is not initialized.</exception>
        ///  <returns>
        ///         <strong>True</strong> if the specified certificate is signed this CRL. Otherwise <strong>False</strong>.
        ///  </returns>
        public Boolean VerifySignature(X509Certificate2 issuer, Boolean strict = false)
        {
            if (RawData == null)
            {
                throw new UninitializedObjectException();
            }
            var signedInfo = new SignedContentBlob(RawData, ContentBlobType.SignedBlob);

            return(MessageSigner.VerifyData(signedInfo, issuer.PublicKey));
        }
示例#5
0
        /// <summary>
        /// Hashes and encodes CRL object from builder information. Instead of signing, CRL is hashed.
        /// </summary>
        /// <param name="hasherInfo">
        /// Issuer certificate to use as a CRL issuer. Issuer certificate is not required to have private key.
        /// </param>
        /// <returns>An instance of generated CRL object.</returns>
        public X509CRL2 BuildAndHash(X509Certificate2 hasherInfo)
        {
            var dummyBlob = new SignedContentBlob(new Byte[] { 0 }, ContentBlobType.ToBeSignedBlob);

            dummyBlob.Hash(new Oid2(HashingAlgorithm, false));
            List <Byte> tbs  = buildTbs(dummyBlob.SignatureAlgorithm.RawData, hasherInfo);
            var         blob = new SignedContentBlob(tbs.ToArray(), ContentBlobType.ToBeSignedBlob);

            blob.Hash(new Oid2(HashingAlgorithm, false));
            return(new X509CRL2(blob.Encode()));
        }
示例#6
0
        /// <summary>
        /// Signs and encodes CRL object from builder information.
        /// </summary>
        /// <param name="signerInfo">Certificate which is used to sign CRL.</param>
        /// <returns>An instance of generated signed CRL object.</returns>
        public X509CRL2 BuildAndSign(MessageSigner signerInfo)
        {
            if (signerInfo == null)
            {
                throw new ArgumentNullException(nameof(signerInfo));
            }

            // create dummy blob, sign/hash it to get proper encoded signature algorithm identifier.
            var dummyBlob = new SignedContentBlob(new Byte[] { 0 }, ContentBlobType.ToBeSignedBlob);

            dummyBlob.Sign(signerInfo);
            // generate tbs
            List <Byte> tbs = buildTbs(dummyBlob.SignatureAlgorithm.RawData, signerInfo.SignerCertificate);

            // now create correct blob and sign/hash it
            var blob = new SignedContentBlob(tbs.ToArray(), ContentBlobType.ToBeSignedBlob);

            blob.Sign(signerInfo);
            return(new X509CRL2(blob.Encode()));
        }
示例#7
0
        /// <summary>
        /// Verifies signature of a signed blob by using specified public key.
        /// </summary>
        /// <param name="blob"></param>
        /// <param name="publicKey"></param>
        /// <returns></returns>
        /// <remarks>
        /// This method is suitable to validate certificate signing requests (CSR) or other data
        /// when signing key pair exist outside of X.509 certificate object.
        /// </remarks>
        public static Boolean VerifyData(SignedContentBlob blob, PublicKey publicKey)
        {
            if (blob == null)
            {
                throw new ArgumentNullException(nameof(blob));
            }
            if (publicKey == null)
            {
                throw new ArgumentNullException(nameof(publicKey));
            }

            if (blob.BlobType != ContentBlobType.SignedBlob)
            {
                throw new InvalidOperationException("The blob is not signed.");
            }

            using (var signerInfo = new MessageSigner()) {
                signerInfo.acquirePublicKey(publicKey);
                signerInfo.getConfiguration(blob.SignatureAlgorithm.RawData);
                return(signerInfo.VerifyData(blob.ToBeSignedData, blob.GetRawSignature()));
            }
        }
示例#8
0
        /// <summary>
        /// Gets decoded textual representation (dump) of the current object.
        /// </summary>
        /// <returns>Textual representation of the current object.</returns>
        public virtual String Format()
        {
            var SB   = new StringBuilder();
            var blob = new SignedContentBlob(RawData, ContentBlobType.SignedBlob);

            SB.Append(
                $@"PKCS10 Certificate Request:
Version: {Version}
Subject:
    {Subject ?? "EMPTY"}

{PublicKey.Format().TrimEnd()}
Request attributes (Count={Attributes.Count}):{formatAttributes().TrimEnd()}
Request extensions (Count={Extensions.Count}):{formatExtensions().TrimEnd()}
{blob.SignatureAlgorithm.ToString().TrimEnd()}    
Signature: Unused bits={blob.Signature.UnusedBits}
    {AsnFormatter.BinaryToString(blob.Signature.Value.ToArray(), EncodingType.HexAddress).Replace("\r\n", "\r\n    ")}
Signature matches Public Key: {SignatureIsValid}
");

            return(SB.ToString());
        }
示例#9
0
        /// <summary>
        /// Populates current object with data from ASN.1-encoded byte array that represents encoded PKCS#10
        /// certificate request.
        /// </summary>
        /// <param name="rawData">ASN.1-encoded byte array.</param>
        /// <exception cref="ArgumentNullException"><strong>rawData</strong> parameter is null.</exception>
        protected void Decode(Byte[] rawData)
        {
            if (rawData == null)
            {
                throw new ArgumentNullException(nameof(rawData));
            }
            var blob = new SignedContentBlob(rawData, ContentBlobType.SignedBlob);

            // at this point we can set signature algorithm and populate RawData
            SignatureAlgorithm = blob.SignatureAlgorithm.AlgorithmId;
            Asn1Reader asn = new Asn1Reader(blob.ToBeSignedData);

            getVersion(asn);
            getSubject(asn);
            getPublicKey(asn);
            // if we reach this far, then we can verify request attribute.
            SignatureIsValid = MessageSigner.VerifyData(blob, PublicKey);
            asn.MoveNextCurrentLevel();
            if (asn.Tag == 0xa0)
            {
                getAttributes(asn);
            }
            RawData = rawData;
        }
示例#10
0
        void m_decode(Byte[] rawData)
        {
            try {
                Type = X509CrlType.BaseCrl;
                var signedInfo = new SignedContentBlob(rawData, ContentBlobType.SignedBlob);
                // signature and alg
                signature          = signedInfo.Signature.Value;
                sigUnused          = signedInfo.Signature.UnusedBits;
                SignatureAlgorithm = signedInfo.SignatureAlgorithm.AlgorithmId;
                // tbs
                Asn1Reader asn = new Asn1Reader(signedInfo.ToBeSignedData);
                if (!asn.MoveNext())
                {
                    throw new Asn1InvalidTagException();
                }
                // version
                if (asn.Tag == (Byte)Asn1Type.INTEGER)
                {
                    Version = (Int32)Asn1Utils.DecodeInteger(asn.GetTagRawData()) + 1;
                    asn.MoveNextCurrentLevel();
                }
                else
                {
                    Version = 1;
                }
                // hash algorithm
                var h = new AlgorithmIdentifier(asn.GetTagRawData());
                if (h.AlgorithmId.Value != SignatureAlgorithm.Value)
                {
                    throw new CryptographicException("Algorithm mismatch.");
                }
                if (!asn.MoveNextCurrentLevel())
                {
                    throw new Asn1InvalidTagException();
                }
                // issuer
                IssuerName = new X500DistinguishedName(asn.GetTagRawData());
                // NextUpdate, RevokedCerts and Extensions are optional. Ref: RFC5280, p.118
                if (!asn.MoveNextCurrentLevel())
                {
                    throw new Asn1InvalidTagException();
                }
                switch (asn.Tag)
                {
                case (Byte)Asn1Type.UTCTime:
                    ThisUpdate = Asn1Utils.DecodeUTCTime(asn.GetTagRawData());
                    break;

                case (Byte)Asn1Type.Generalizedtime:
                    ThisUpdate = Asn1Utils.DecodeGeneralizedTime(asn.GetTagRawData());
                    break;

                default:
                    throw new Asn1InvalidTagException();
                }
                if (!asn.MoveNextCurrentLevel())
                {
                    return;
                }
                switch (asn.Tag)
                {
                case (Byte)Asn1Type.UTCTime:
                case (Byte)Asn1Type.Generalizedtime:
                    switch (asn.Tag)
                    {
                    case (Byte)Asn1Type.UTCTime:
                        NextUpdate = Asn1Utils.DecodeUTCTime(asn.GetTagRawData());
                        break;

                    case (Byte)Asn1Type.Generalizedtime:
                        NextUpdate = Asn1Utils.DecodeGeneralizedTime(asn.GetTagRawData());
                        break;

                    default:
                        throw new Asn1InvalidTagException();
                    }
                    if (!asn.MoveNextCurrentLevel())
                    {
                        return;
                    }
                    if (asn.Tag == 48)
                    {
                        getRevCerts(asn);
                        if (!asn.MoveNextCurrentLevel())
                        {
                            return;
                        }
                        getExts(asn);
                    }
                    else
                    {
                        getExts(asn);
                    }
                    break;

                case 48:
                    if (asn.Tag == 48)
                    {
                        getRevCerts(asn);
                        if (!asn.MoveNextCurrentLevel())
                        {
                            return;
                        }
                        getExts(asn);
                    }
                    else
                    {
                        getExts(asn);
                    }
                    break;

                default:
                    getExts(asn);
                    break;
                }
            } catch (Exception e) {
                throw new CryptographicException("Cannot find the requested object.", e);
            }
        }
示例#11
0
        ///  <summary>
        ///		Verifies whether the specified certificate is an issuer of this CRL by verifying CRL signature
        ///		against specified certificate's public key.
        ///  </summary>
        ///  <param name="issuer">
        ///		A potential issuer's certificate.
        /// </param>
        /// <param name="strict">
        ///		Specifies whether to perform CRL issuer and certificate's subject name binary comparison. This parameter is not implemented.
        /// </param>
        /// <exception cref="CryptographicException">
        ///     The data is invalid.
        ///  </exception>
        ///  <returns>
        ///         <strong>True</strong> if the specified certificate is signed this CRL. Otherwise <strong>False</strong>.
        ///  </returns>
        public Boolean VerifySignature(X509Certificate2 issuer, Boolean strict = false)
        {
            var signedInfo = new SignedContentBlob(_rawData, ContentBlobType.SignedBlob);

            return(MessageSigner.VerifyData(signedInfo, issuer.PublicKey));
        }