public SimpleCA(string countryCode, string organization, string orgunit, string commonName) { var distinguishedName = $"C={countryCode};O={organization};OU={orgunit};CN={commonName}"; //var distinguishedName = "C=US;O=Microsoft;OU=WGA;CN=TedSt"; //CN={commonName}/OU={organizationUnit}/O={organization}/DC={domain}/STREET={address}/L={locality}/ST={state}/C={country}/DC={domainComponent}" var dn = new System.Security.Cryptography.X509Certificates.X500DistinguishedName( distinguishedName ); var key = System.Security.Cryptography.RSA.Create(); key.KeySize = 4096; var hash = System.Security.Cryptography.HashAlgorithmName.SHA512; var req = new System.Security.Cryptography.X509Certificates.CertificateRequest(dn, key, hash, RSASignaturePadding.Pss); var q = Oid.FromFriendlyName("", OidGroup.EnhancedKeyUsage); Oid.FromOidValue("", OidGroup.EnhancedKeyUsage); var r = new OidCollection(); r.Add(q); var v = new X509EnhancedKeyUsageExtension(r, false); req.CertificateExtensions.Add(SetEnhancedKeyUsage(keyCertSign: true)); req.CertificateExtensions.Add(SetBasicConstraints(true)); req.CertificateExtensions.Add(v); var now = DateTimeOffset.UtcNow; var startDate = now - TimeSpan.FromMinutes(5); var endDate = DateTimeOffset.UtcNow + TimeSpan.FromDays(365.25 * 10); rootCert = req.CreateSelfSigned(startDate, endDate); rootKey = key; var rootKeyChain = rootCert.Export(X509ContentType.Pkcs12); }
public void GenerateHierrachyUsingNetClass() { using (RSA parent = RSA.Create(4096)) using (RSA rsa = RSA.Create(2048)) { System.Security.Cryptography.X509Certificates.CertificateRequest parentReq = new System.Security.Cryptography.X509Certificates.CertificateRequest( "CN=Experimental Issuing Authority", parent, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1); parentReq.CertificateExtensions.Add( new X509BasicConstraintsExtension(true, false, 0, true)); parentReq.CertificateExtensions.Add( new X509SubjectKeyIdentifierExtension(parentReq.PublicKey, false)); //var csr = parentReq.CreateSigningRequest(); using (X509Certificate2 parentCert = parentReq.CreateSelfSigned( DateTimeOffset.UtcNow.AddDays(-45), DateTimeOffset.UtcNow.AddDays(365))) { CertificateRequest req = new CertificateRequest( "CN=Valid-Looking Timestamp Authority", rsa, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1); req.CertificateExtensions.Add( new X509BasicConstraintsExtension(true, false, 0, false)); req.CertificateExtensions.Add( new X509KeyUsageExtension( X509KeyUsageFlags.DigitalSignature | X509KeyUsageFlags.NonRepudiation, false)); //https://pkisolutions.com/object-identifiers-oid-in-pki/ //https://docs.microsoft.com/en-us/windows/desktop/seccertenroll/supported-extensions req.CertificateExtensions.Add( new X509EnhancedKeyUsageExtension( new OidCollection { new Oid("1.3.6.1.5.5.7.3.8") }, true)); req.CertificateExtensions.Add( new X509SubjectKeyIdentifierExtension(req.PublicKey, false)); req.CreateSigningRequest(); using (X509Certificate2 cert = req.Create( parentCert, DateTimeOffset.UtcNow.AddDays(-1), DateTimeOffset.UtcNow.AddDays(90), new byte[] { 1, 2, 3, 4 })) { // Do something with these certs, like export them to PFX, // or add them to an X509Store, or whatever. } using (X509Certificate2 cert = req.Create( parentCert, DateTimeOffset.UtcNow.AddDays(-1), DateTimeOffset.UtcNow.AddDays(90), new byte[] { 1, 2, 3, 4 })) { // Do something with these certs, like export them to PFX, // or add them to an X509Store, or whatever. } } } }
/// <summary> /// Create signed certificate from request /// </summary> /// <param name="request"></param> /// <param name="signer"></param> /// <param name="issuer"></param> /// <param name="notBefore"></param> /// <param name="notAfter"></param> /// <param name="serialNumber"></param> /// <returns></returns> public static X509Certificate2 Create(this CertificateRequest request, IDigestSigner signer, Certificate issuer, DateTime notBefore, DateTime notAfter, byte[] serialNumber) { return(Create(request, signer, issuer.Subject, issuer.KeyHandle, issuer.IssuerPolicies.SignatureType.Value, notBefore, notAfter, serialNumber)); }
/// <summary> /// Get public key from request /// </summary> /// <param name="request"></param> /// <returns></returns> public static Key GetPublicKey(this CertificateRequest request) { var csr = request.CreateSigningRequest().ToCertificationRequestInfo(); return(csr.GetPublicKey()); }
private static unsafe CertificateRequest LoadSigningRequest( ReadOnlySpan <byte> pkcs10, bool permitTrailingData, HashAlgorithmName signerHashAlgorithm, out int bytesConsumed, CertificateRequestLoadOptions options, RSASignaturePadding?signerSignaturePadding) { ArgumentException.ThrowIfNullOrEmpty(signerHashAlgorithm.Name, nameof(signerHashAlgorithm)); if ((options & ~AllOptions) != 0) { throw new ArgumentOutOfRangeException(nameof(options), options, SR.Argument_InvalidFlag); } bool skipSignatureValidation = (options & CertificateRequestLoadOptions.SkipSignatureValidation) != 0; bool unsafeLoadCertificateExtensions = (options & CertificateRequestLoadOptions.UnsafeLoadCertificateExtensions) != 0; try { AsnValueReader outer = new AsnValueReader(pkcs10, AsnEncodingRules.DER); int encodedLength = outer.PeekEncodedValue().Length; AsnValueReader pkcs10Asn = outer.ReadSequence(); CertificateRequest req; if (!permitTrailingData) { outer.ThrowIfNotEmpty(); } fixed(byte *p10ptr = pkcs10) { using (PointerMemoryManager <byte> manager = new PointerMemoryManager <byte>(p10ptr, encodedLength)) { ReadOnlyMemory <byte> rebind = manager.Memory; ReadOnlySpan <byte> encodedRequestInfo = pkcs10Asn.PeekEncodedValue(); CertificationRequestInfoAsn requestInfo; AlgorithmIdentifierAsn algorithmIdentifier; ReadOnlySpan <byte> signature; int signatureUnusedBitCount; CertificationRequestInfoAsn.Decode(ref pkcs10Asn, rebind, out requestInfo); AlgorithmIdentifierAsn.Decode(ref pkcs10Asn, rebind, out algorithmIdentifier); if (!pkcs10Asn.TryReadPrimitiveBitString(out signatureUnusedBitCount, out signature)) { throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding); } pkcs10Asn.ThrowIfNotEmpty(); if (requestInfo.Version < 0) { throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding); } // They haven't bumped from v0 to v1 as of 2022. const int MaxSupportedVersion = 0; if (requestInfo.Version != MaxSupportedVersion) { throw new CryptographicException( SR.Format( SR.Cryptography_CertReq_Load_VersionTooNew, requestInfo.Version, MaxSupportedVersion)); } PublicKey publicKey = PublicKey.DecodeSubjectPublicKeyInfo(ref requestInfo.SubjectPublicKeyInfo); if (!skipSignatureValidation) { // None of the supported signature algorithms support signatures that are not full bytes. // So, shortcut the verification on the bit length if (signatureUnusedBitCount != 0 || !VerifyX509Signature(encodedRequestInfo, signature, publicKey, algorithmIdentifier)) { throw new CryptographicException(SR.Cryptography_CertReq_SignatureVerificationFailed); } } X500DistinguishedName subject = new X500DistinguishedName(requestInfo.Subject.Span); req = new CertificateRequest( subject, publicKey, signerHashAlgorithm, signerSignaturePadding); if (requestInfo.Attributes is not null) { bool foundCertExt = false; foreach (AttributeAsn attr in requestInfo.Attributes) { if (attr.AttrType == Oids.Pkcs9ExtensionRequest) { if (foundCertExt) { throw new CryptographicException( SR.Cryptography_CertReq_Load_DuplicateExtensionRequests); } foundCertExt = true; if (attr.AttrValues.Length != 1) { throw new CryptographicException( SR.Cryptography_CertReq_Load_DuplicateExtensionRequests); } AsnValueReader extsReader = new AsnValueReader( attr.AttrValues[0].Span, AsnEncodingRules.DER); AsnValueReader exts = extsReader.ReadSequence(); extsReader.ThrowIfNotEmpty(); // Minimum length is 1, so do..while do { X509ExtensionAsn.Decode(ref exts, rebind, out X509ExtensionAsn extAsn); if (unsafeLoadCertificateExtensions) { X509Extension ext = new X509Extension( extAsn.ExtnId, extAsn.ExtnValue.Span, extAsn.Critical); X509Extension?rich = X509Certificate2.CreateCustomExtensionIfAny(extAsn.ExtnId); if (rich is not null) { rich.CopyFrom(ext); req.CertificateExtensions.Add(rich); } else { req.CertificateExtensions.Add(ext); } } } while (exts.HasData); } else { if (attr.AttrValues.Length == 0) { throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding); } foreach (ReadOnlyMemory <byte> val in attr.AttrValues) { req.OtherRequestAttributes.Add( new AsnEncodedData(attr.AttrType, val.Span)); } } } } } } bytesConsumed = encodedLength; return(req); } catch (AsnContentException e) { throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding, e); } }