public X509Extension Build(bool critical = false) { return(new X509Extension( Oids.SubjectAltName, DerEncoder.ConstructSequence(_encodedTlvs), critical)); }
public override byte[] GetSignatureAlgorithmIdentifier(HashAlgorithmName hashAlgorithm) { string oid; if (hashAlgorithm == HashAlgorithmName.SHA256) { oid = Oids.RsaPkcs1Sha256; } else if (hashAlgorithm == HashAlgorithmName.SHA384) { oid = Oids.RsaPkcs1Sha384; } else if (hashAlgorithm == HashAlgorithmName.SHA512) { oid = Oids.RsaPkcs1Sha512; } else { throw new ArgumentOutOfRangeException( nameof(hashAlgorithm), hashAlgorithm, SR.Format(SR.Cryptography_UnknownHashAlgorithm, hashAlgorithm.Name)); } return(DerEncoder.ConstructSequence( DerEncoder.SegmentedEncodeOid(oid), DerEncoder.SegmentedEncodeNull())); }
public override byte[] SignData(byte[] data, HashAlgorithmName hashAlgorithm) { byte[] ieeeFormat = _key.SignData(data, hashAlgorithm); Debug.Assert(ieeeFormat.Length % 2 == 0); int segmentLength = ieeeFormat.Length / 2; return(DerEncoder.ConstructSequence( DerEncoder.SegmentedEncodeUnsignedInteger(ieeeFormat, 0, segmentLength), DerEncoder.SegmentedEncodeUnsignedInteger(ieeeFormat, segmentLength, segmentLength))); }
internal byte[] Sign(X509SignatureGenerator signatureGenerator, HashAlgorithmName hashAlgorithm) { if (signatureGenerator == null) { throw new ArgumentNullException(nameof(signatureGenerator)); } byte[] encoded = Encode(signatureGenerator, hashAlgorithm); byte[] signature = signatureGenerator.SignData(encoded, hashAlgorithm); return(DerEncoder.ConstructSequence( encoded.WrapAsSegmentedForSequence(), signatureGenerator.GetSignatureAlgorithmIdentifier(hashAlgorithm).WrapAsSegmentedForSequence(), DerEncoder.SegmentedEncodeBitString(signature))); }
protected override PublicKey BuildPublicKey() { RSAParameters parameters = _key.ExportParameters(false); byte[] rsaPublicKey = DerEncoder.ConstructSequence( DerEncoder.SegmentedEncodeUnsignedInteger(parameters.Modulus), DerEncoder.SegmentedEncodeUnsignedInteger(parameters.Exponent)); Oid oid = new Oid(Oids.RsaRsa); // The OID is being passed to everything here because that's what // X509Certificate2.PublicKey does. return(new PublicKey( oid, // Encode the DER-NULL even though it is OPTIONAL, because everyone else does. // // This is due to one version of the ASN.1 not including OPTIONAL, and that was // the version that got predominately implemented for RSA. Now it's convention. new AsnEncodedData(oid, new byte[] { 0x05, 0x00 }), new AsnEncodedData(oid, rsaPublicKey))); }
internal byte[] ToPkcs10Request(X509SignatureGenerator signatureGenerator, HashAlgorithmName hashAlgorithm) { // State validation should be runtime checks if/when this becomes public API Debug.Assert(signatureGenerator != null); Debug.Assert(Subject != null); Debug.Assert(PublicKey != null); // CertificationRequest ::= SEQUENCE { // certificationRequestInfo CertificationRequestInfo, // signatureAlgorithm AlgorithmIdentifier{ { SignatureAlgorithms } }, // signature BIT STRING // } byte[] encoded = Encode(); byte[] signature = signatureGenerator.SignData(encoded, hashAlgorithm); return(DerEncoder.ConstructSequence( encoded.WrapAsSegmentedForSequence(), signatureGenerator.GetSignatureAlgorithmIdentifier(hashAlgorithm).WrapAsSegmentedForSequence(), DerEncoder.SegmentedEncodeBitString(signature))); }
private byte[] Encode() { // CertificationRequestInfo::= SEQUENCE { // version INTEGER { v1(0) } (v1,...), // subject Name, // subjectPKInfo SubjectPublicKeyInfo{ { PKInfoAlgorithms } }, // attributes[0] Attributes{ { CRIAttributes } } // } // // Attributes { ATTRIBUTE:IOSet } ::= SET OF Attribute{{ IOSet }} byte[][] attrSet = Attributes.SegmentedEncodeAttributeSet(); // Replace the tag with ContextSpecific0. attrSet[0][0] = DerSequenceReader.ContextSpecificConstructedTag0; return(DerEncoder.ConstructSequence( s_encodedVersion, Subject.RawData.WrapAsSegmentedForSequence(), PublicKey.SegmentedEncodeSubjectPublicKeyInfo(), attrSet)); }
private static byte[] EncodeAttribute(IEnumerable <X509Extension> extensions) { if (extensions == null) { throw new ArgumentNullException(nameof(extensions)); } // extensionRequest ATTRIBUTE ::= { // WITH SYNTAX ExtensionRequest // SINGLE VALUE TRUE // ID pkcs-9-at-extensionRequest // } // // ExtensionRequest ::= Extensions // // Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension // // Extension ::= SEQUENCE { // extnID OBJECT IDENTIFIER, // critical BOOLEAN DEFAULT FALSE, // extnValue OCTET STRING } List <byte[][]> encodedExtensions = new List <byte[][]>(); foreach (X509Extension extension in extensions) { if (extension == null) { continue; } encodedExtensions.Add(extension.SegmentedEncodedX509Extension()); } // The SEQUENCE over the encodedExtensions list is the value of // Extensions/ExtensionRequest. return(DerEncoder.ConstructSequence(encodedExtensions.ToArray())); }
private byte[] Encode(X509SignatureGenerator signatureGenerator, HashAlgorithmName hashAlgorithm) { // State validation should be runtime checks if/when this becomes public API Debug.Assert(Subject != null); Debug.Assert(PublicKey != null); // Under a public API model we could allow these to be null for a self-signed case. Debug.Assert(SerialNumber != null); Debug.Assert(Issuer != null); List <byte[][]> encodedFields = new List <byte[][]>(); byte version = Version; if (version != 0) { byte[][] encodedVersion = DerEncoder.ConstructSegmentedSequence( DerEncoder.SegmentedEncodeUnsignedInteger(new[] { version })); encodedVersion[0][0] = DerSequenceReader.ContextSpecificConstructedTag0; encodedFields.Add(encodedVersion); } encodedFields.Add(DerEncoder.SegmentedEncodeUnsignedInteger(SerialNumber)); // SignatureAlgorithm: Use the specified value, or ask the generator (without mutating the class) byte[] signatureAlgorithm = SignatureAlgorithm ?? signatureGenerator.GetSignatureAlgorithmIdentifier(hashAlgorithm); EncodingHelpers.ValidateSignatureAlgorithm(signatureAlgorithm); encodedFields.Add(signatureAlgorithm.WrapAsSegmentedForSequence()); // For public API allowing self-sign ease-of-use, this could be (Issuer ?? Subject). encodedFields.Add(Issuer.RawData.WrapAsSegmentedForSequence()); encodedFields.Add( DerEncoder.ConstructSegmentedSequence( EncodeValidityField(NotBefore, nameof(NotBefore)), EncodeValidityField(NotAfter, nameof(NotAfter)))); encodedFields.Add(Subject.RawData.WrapAsSegmentedForSequence()); encodedFields.Add(PublicKey.SegmentedEncodeSubjectPublicKeyInfo()); // Issuer and Subject Unique ID values would go here, if they were supported. if (Extensions.Count > 0) { Debug.Assert(version >= 2); List <byte[][]> encodedExtensions = new List <byte[][]>(Extensions.Count); // extensions[3] Extensions OPTIONAL // // Since this doesn't say IMPLICIT, it will look like // // A3 [length] // 30 [length] // First Extension // Second Extension // ... // An interesting quirk of skipping null values here is that // Extensions.Count == 0 => no extensions // Extensions.ContainsOnly(null) => empty extensions list HashSet <string> usedOids = new HashSet <string>(Extensions.Count); foreach (X509Extension extension in Extensions) { if (extension == null) { continue; } if (!usedOids.Add(extension.Oid.Value)) { throw new InvalidOperationException( SR.GetString(SR.Cryptography_CertReq_DuplicateExtension, extension.Oid.Value)); } encodedExtensions.Add(extension.SegmentedEncodedX509Extension()); } byte[][] extensionField = DerEncoder.ConstructSegmentedSequence( DerEncoder.ConstructSegmentedSequence(encodedExtensions)); extensionField[0][0] = DerSequenceReader.ContextSpecificConstructedTag3; encodedFields.Add(extensionField); } return(DerEncoder.ConstructSequence(encodedFields)); }
public override byte[] GetSignatureAlgorithmIdentifier(HashAlgorithmName hashAlgorithm) { // If we ever support options in PSS (like MGF-2, if such an MGF is ever invented) // Or, more reasonably, supporting a custom value for the salt size. if (_padding != RSASignaturePadding.Pss) { throw new CryptographicException(SR.Cryptography_InvalidPaddingMode); } uint cbSalt; string digestOid; if (hashAlgorithm == HashAlgorithmName.SHA256) { cbSalt = 256 / 8; digestOid = Oids.Sha256; } else if (hashAlgorithm == HashAlgorithmName.SHA384) { cbSalt = 384 / 8; digestOid = Oids.Sha384; } else if (hashAlgorithm == HashAlgorithmName.SHA512) { cbSalt = 512 / 8; digestOid = Oids.Sha512; } else { throw new ArgumentOutOfRangeException( nameof(hashAlgorithm), hashAlgorithm, SR.Format(SR.Cryptography_UnknownHashAlgorithm, hashAlgorithm.Name)); } // RSASSA-PSS-params comes from RFC 4055, section 3.1: // https://tools.ietf.org/html/rfc4055#section-3.1 // // RSASSA-PSS-params ::= SEQUENCE { // hashAlgorithm [0] HashAlgorithm DEFAULT sha1Identifier, // maskGenAlgorithm [1] MaskGenAlgorithm DEFAULT mgf1SHA1Identifier, // saltLength [2] INTEGER DEFAULT 20, // trailerField [3] INTEGER DEFAULT 1 } // // mgf1SHA1Identifier AlgorithmIdentifier ::= { id-mgf1, sha1Identifier } // sha1Identifier AlgorithmIdentifier ::= { id-sha1, NULL } // (and similar for SHA256/384/512) // // RFC 5754 says that the NULL for SHA2 (256/384/512) MUST be omitted // (https://tools.ietf.org/html/rfc5754#section-2) (and that you MUST // be able to read it even if someone wrote it down) // Since we // * don't support SHA-1 in this class // * only support MGF-1 // * don't support the MGF PRF being different than hashAlgorithm // * use saltLength==hashLength // * don't allow custom trailer // we don't have to worry about any of the DEFAULTs. (specify, specify, specify, omit). byte[][] hashAlgorithmAlgId = DerEncoder.ConstructSegmentedSequence( DerEncoder.SegmentedEncodeOid(digestOid)); byte[][] hashAlgorithmField = DerEncoder.ConstructSegmentedSequence(hashAlgorithmAlgId); hashAlgorithmField[0][0] = DerSequenceReader.ContextSpecificConstructedTag0; byte[][] maskGenField = DerEncoder.ConstructSegmentedSequence( DerEncoder.ConstructSegmentedSequence( DerEncoder.SegmentedEncodeOid(Oids.Mgf1), hashAlgorithmAlgId)); maskGenField[0][0] = DerSequenceReader.ContextSpecificConstructedTag1; byte[][] saltLengthField = DerEncoder.ConstructSegmentedSequence( DerEncoder.SegmentedEncodeUnsignedInteger(cbSalt)); saltLengthField[0][0] = DerSequenceReader.ContextSpecificConstructedTag2; return(DerEncoder.ConstructSequence( DerEncoder.SegmentedEncodeOid(Oids.RsaSsaPss), // RSASSA-PSS-params DerEncoder.ConstructSegmentedSequence( hashAlgorithmField, maskGenField, saltLengthField))); }