-----BEGIN CERTIFICATE REQUEST-----
MIIDejCCAmICAQAwZTE0MDIGCgmSJom....
-----END CERTIFICATE REQUEST-----
它是使用.NET 4.7.2CertificateRequest
生成的,类似于本问题中的答案:使用纯.NET Framework生成和签名证书请求
然后将序列化的CSR发送到服务器,服务器需要创建证书--问题是如何做到这一点。
解析一个认证请求(口语中称为证书签名请求或CSR)并盲目签名是一种非常非常糟糕的操作实践。
如果您想成为一个证书颁发机构,甚至是一个私有的证书颁发机构,那么您应该阅读并理解CA/Browser论坛当前(无论何时阅读这篇文章)的基线需求文档(https://cabforum.org/baseline-requirements-documents/)中的所有内容。也许你故意决定某件事对你不适用,但至少这是故意的。
至少您应该检查请求:
internal static class CertificationRequestDecoder
{
private const string BadPemRequest = "Input is not a PEM-encoded Certification Request.";
/// <summary>
/// Load a CertificateRequest from a PEM-encoded Certification Request
/// (a.k.a. Certificate Signing Request, CSR)
/// </summary>
/// <param name="pem">The PEM-encoded Certification Request</param>
/// <param name="signatureHashAlgorithm">
/// The hash algorithm to be used with the CA signature.
/// </param>
/// <returns>
/// A certificate request object containing the same data as the signing request.
/// </returns>
/// <exception cref="ArgumentNullException"><paramref name="pem"/> is <c>null</c>.</exception>
/// <exception cref="ArgumentException">
/// <paramref name="pem"/> is not a well-formed PEM encoding for a Certification Request.
/// </exception>
/// <exception cref="AsnContentException">
/// <paramref name="pem"/> does not contain a well-formed Certification Request.
/// </exception>
/// <exception cref="InvalidOperationException">
/// The request contains unsupported elements.
/// </exception>
/// <exception cref="CryptographicException">
/// The Certification Request signature is invalid.
/// </exception>
/// <seealso cref="DecodeDer(ReadOnlyMemory{byte},HashAlgorithmName"/>
internal static CertificateRequest DecodePem(
string pem,
HashAlgorithmName signatureHashAlgorithm)
{
if (pem == null)
throw new ArgumentNullException(nameof(pem));
// This PEM reader is overly lax. It should check for a newline at the end of preEB
// and another at the beginning of postEB, but it skips it for Unix/Windows newline
// reasons.
//
// After all, this is just a sample, right?
const string PreEB = "-----BEGIN CERTIFICATE REQUEST-----";
const string PostEB = "-----END CERTIFICATE REQUEST-----";
int startIdx = pem.IndexOf(PreEB, StringComparison.Ordinal);
int endIdx = pem.IndexOf(PostEB, StringComparison.Ordinal);
if (startIdx < 0 || endIdx < 0)
throw new ArgumentException(BadPemRequest, nameof(pem));
if (startIdx != 0 && !string.IsNullOrWhiteSpace(pem.Substring(0, startIdx)))
throw new ArgumentException(BadPemRequest, nameof(pem));
if (endIdx < startIdx || !string.IsNullOrWhiteSpace(pem.Substring(endIdx + PostEB.Length)))
throw new ArgumentException(BadPemRequest, nameof(pem));
byte[] der;
try
{
int base64Start = startIdx + PreEB.Length;
string base64 = pem.Substring(base64Start, endIdx - base64Start);
der = Convert.FromBase64String(base64);
}
catch (FormatException e)
{
throw new ArgumentException(BadPemRequest, nameof(pem), e);
}
return DecodeDer(der, signatureHashAlgorithm);
}
internal static CertificateRequest DecodeDer(
byte[] der,
HashAlgorithmName signatureHashAlgorithm)
{
if (der == null)
throw new ArgumentNullException(nameof(der));
return DecodeDer(der.AsMemory(), signatureHashAlgorithm);
}
/// <summary>
/// Load a CertificateRequest from a DER-encoded Certification Request
/// (a.k.a. Certificate Signing Request, CSR)
/// </summary>
/// <param name="der">The DER-encoded Certification Request.</param>
/// <param name="signatureHashAlgorithm">
/// The hash algorithm to be used with the CA signature.
/// </param>
/// <returns>
/// A certificate request object containing the same data as the signing request.
/// </returns>
/// <exception cref="FormatException">
/// <paramref name="der"/> is not well-formed.
/// </exception>
/// <exception cref="InvalidOperationException">
/// The request contains unsupported elements.
/// </exception>
/// <exception cref="CryptographicException">
/// The Certification Request signature is invalid.
/// </exception>
/// <remarks>
/// This routine does not perform any sort of operational policy.
/// The caller is responsible for verifying that only valid extensions
/// are used, that the subject name is appropriate, and any other operational
/// concerns.
/// </remarks>
internal static CertificateRequest DecodeDer(
ReadOnlyMemory<byte> der,
HashAlgorithmName signatureHashAlgorithm)
{
AsnReader reader = new AsnReader(der, AsnEncodingRules.DER);
AsnReader certificationRequest = reader.ReadSequence();
reader.ThrowIfNotEmpty();
byte[] encodedRequestInfo = certificationRequest.PeekEncodedValue().ToArray();
AsnReader certificationRequestInfo = certificationRequest.ReadSequence();
AsnReader algorithm = certificationRequest.ReadSequence();
byte[] signature = certificationRequest.ReadBitString(out int unused);
if (unused != 0)
{
throw new InvalidOperationException("The signature was not complete bytes.");
}
certificationRequest.ThrowIfNotEmpty();
string algorithmOid = algorithm.ReadObjectIdentifier();
HashAlgorithmName hashAlg;
RSASignaturePadding signaturePadding = RSASignaturePadding.Pkcs1;
// This only supports RSA.
// Other algorithms could be added.
switch (algorithmOid)
{
case "1.2.840.113549.1.1.5":
hashAlg = HashAlgorithmName.SHA1;
break;
case "1.2.840.113549.1.1.11":
hashAlg = HashAlgorithmName.SHA256;
break;
case "1.2.840.113549.1.1.12":
hashAlg = HashAlgorithmName.SHA384;
break;
case "1.2.840.113549.1.1.13":
hashAlg = HashAlgorithmName.SHA512;
break;
default:
throw new InvalidOperationException(
$"No support for signature algorithm '{algorithmOid}'");
}
// Since only RSA-SSA-PKCS1 made it here, we know the parameters are missing, or NULL.
if (algorithm.HasData)
{
algorithm.ReadNull();
}
algorithm.ThrowIfNotEmpty();
CertificateRequest certReq =
DecodeCertificationRequestInfo(certificationRequestInfo, signatureHashAlgorithm);
RSA pubKey = GetRSA(certReq.PublicKey);
if (pubKey == null)
{
throw new InvalidOperationException("Requested public key was not an RSA key.");
}
if (!pubKey.VerifyData(encodedRequestInfo, signature, hashAlg, signaturePadding))
{
throw new CryptographicException();
}
return certReq;
}
private static CertificateRequest DecodeCertificationRequestInfo(
AsnReader certReqInfo,
HashAlgorithmName signatureHashAlgorithm)
{
//https://tools.ietf.org/html/rfc2986#section-4.1
// CertificationRequestInfo::= SEQUENCE {
// version INTEGER { v1(0) } (v1, ...),
// subject Name,
// subjectPKInfo SubjectPublicKeyInfo{ { PKInfoAlgorithms } },
// attributes[0] Attributes{ { CRIAttributes } }
// }
// As of Sept 2020, there's not a V2 request format.
if (!certReqInfo.TryReadInt32(out int version) || version != 0)
{
throw new InvalidOperationException("Only V1 requests are supported.");
}
byte[] encodedSubject = certReqInfo.ReadEncodedValue().ToArray();
X500DistinguishedName subject = new X500DistinguishedName(encodedSubject);
AsnReader spki = certReqInfo.ReadSequence();
AsnReader reqAttrs =certReqInfo.ReadSetOf(new Asn1Tag(TagClass.ContextSpecific, 0));
certReqInfo.ThrowIfNotEmpty();
// https://tools.ietf.org/html/rfc3280#section-4.1
// SubjectPublicKeyInfo::= SEQUENCE {
// algorithm AlgorithmIdentifier,
// subjectPublicKey BIT STRING
// }
AsnReader pubKeyAlg = spki.ReadSequence();
string algOid = pubKeyAlg.ReadObjectIdentifier();
byte[] algParams;
if (pubKeyAlg.HasData)
{
algParams = pubKeyAlg.ReadEncodedValue().ToArray();
pubKeyAlg.ThrowIfNotEmpty();
}
else
{
algParams = new byte[] { 0x05, 0x00 };
}
byte[] keyBytes = spki.ReadBitString(out int unusedBitCount);
if (unusedBitCount != 0)
{
throw new InvalidOperationException(
"The subjectPublicKey field was not made of full bytes.");
}
PublicKey publicKey = new PublicKey(
new Oid(algOid, null),
new AsnEncodedData(algParams),
new AsnEncodedData(keyBytes));
CertificateRequest request = new CertificateRequest(
subject,
publicKey,
signatureHashAlgorithm);
if (reqAttrs.HasData)
{
// This decode routine only supports one extension: the PKCS#9 extensionRequest
// https://tools.ietf.org/html/rfc2985
// extensionRequest ATTRIBUTE ::= {
// WITH SYNTAX ExtensionRequest
// SINGLE VALUE TRUE
// ID pkcs-9-at-extensionRequest
// }
//
// ExtensionRequest::= Extensions
// https://www.itu.int/ITU-T/formal-language/itu-t/x/x501/2012/InformationFramework.html
// Attribute{ATTRIBUTE: SupportedAttributes} ::= SEQUENCE {
// type ATTRIBUTE.&id({SupportedAttributes}),
// values SET SIZE(0..MAX) OF ATTRIBUTE.&Type({SupportedAttributes}{@type}),
// valuesWithContext SIZE(1..MAX) OF
// SEQUENCE {
// value ATTRIBUTE.&Type({SupportedAttributes}{@type}),
// contextList SET SIZE(1..MAX) OF Context,
// ...
// } OPTIONAL,
// ...
// }
// https://tools.ietf.org/html/rfc5280#section-4.1
// Extensions::= SEQUENCE SIZE(1..MAX) OF Extension
//
// Extension::= SEQUENCE {
// extnID OBJECT IDENTIFIER,
// critical BOOLEAN DEFAULT FALSE,
// extnValue OCTET STRING
// --contains the DER encoding of an ASN.1 value
// --corresponding to the extension type identified
// --by extnID
// }
AsnReader attribute = reqAttrs.ReadSequence();
string attrType = attribute.ReadObjectIdentifier();
AsnReader attrValues = attribute.ReadSetOf();
if (attrType != "1.2.840.113549.1.9.14")
{
throw new InvalidOperationException(
$"Certification Request attribute '{attrType}' is not supported.");
}
// No contexts are defined for the extensionRequest attribute,
// so valuesWithContext can't exist.
attribute.ThrowIfNotEmpty();
// The attribute is single-value, so it must be present
// and there mustn't be a second one.
AsnReader extensions = attrValues.ReadSequence();
attrValues.ThrowIfNotEmpty();
while (extensions.HasData)
{
AsnReader extension = extensions.ReadSequence();
string extnId = extension.ReadObjectIdentifier();
bool critical = false;
byte[] extnValue;
if (extension.PeekTag().HasSameClassAndValue(Asn1Tag.Boolean))
{
critical = extension.ReadBoolean();
}
extnValue = extension.ReadOctetString();
extension.ThrowIfNotEmpty();
X509Extension ext = new X509Extension(
extnId,
extnValue,
critical);
if (CryptoConfig.CreateFromName(extnId) is X509Extension typedExtn)
{
typedExtn.CopyFrom(ext);
ext = typedExtn;
}
request.CertificateExtensions.Add(ext);
}
}
return request;
}
private static RSA GetRSA(PublicKey certReqPublicKey)
{
try
{
return certReqPublicKey.Key as RSA;
}
catch (CryptographicException)
{
}
catch (PlatformNotSupportedException)
{
}
// The try will fail on .NET Framework with any RSA key whose public exponent
// is bigger than uint.MaxValue, because RSACryptoServiceProvider (Windows CAPI)
// doesn't support them.
if (certReqPublicKey.Oid.Value != "1.2.840.113549.1.1.1")
{
throw new InvalidOperationException(
$"The public key algorithm '{certReqPublicKey.Oid.Value}' is not supported.");
}
byte[] encodedParams = certReqPublicKey.EncodedParameters.RawData;
if (encodedParams != null && encodedParams.Length != 0)
{
if (encodedParams.Length != 2 ||
encodedParams[0] != 0x05 ||
encodedParams[1] != 0x00)
{
throw new InvalidOperationException(
"Invalid algorithm parameters for an RSA key.");
}
}
AsnReader encodedKey = new AsnReader(
certReqPublicKey.EncodedKeyValue.RawData,
AsnEncodingRules.DER);
// https://tools.ietf.org/html/rfc3447#appendix-A.1.1
// RSAPublicKey::= SEQUENCE {
// modulus INTEGER, --n
// publicExponent INTEGER --e
// }
AsnReader rsaPublicKey = encodedKey.ReadSequence();
BigInteger modulus = rsaPublicKey.ReadInteger();
BigInteger publicExponent = rsaPublicKey.ReadInteger();
rsaPublicKey.ThrowIfNotEmpty();
byte[] n = modulus.ToByteArray();
byte[] e = publicExponent.ToByteArray();
if (n[n.Length - 1] == 0)
{
Array.Resize(ref n, n.Length - 1);
}
if (e[e.Length - 1] == 0)
{
Array.Resize(ref e, e.Length - 1);
}
Array.Reverse(n);
Array.Reverse(e);
RSAParameters rsaParameters = new RSAParameters
{
Modulus = n,
Exponent = e,
};
RSACng rsaCng = new RSACng();
rsaCng.ImportParameters(rsaParameters);
return rsaCng;
}
}
我正在创建一个Java程序来从服务器获取信息,但我必须从Java程序与服务器执行ssl握手。 我有文件证书用于身份验证,但我不知道如何用java加载该证书,以便java程序可以与我想要从中获取信息的服务器进行“握手”。从哪里开始?
做这件事的好方法是什么?
我试了几个解决方案,为了前任。HTTPS/SSL上的Java客户端证书或获取javax.net.ssl.sslHandShakeException:收到致命警报:handshake_failure错误,从.p12文件中收到的证书和从浏览器导出的证书都不起作用... 更新2: 我尝试了以下方法:https://stackoverflow.com/a/11908693/1215791,并设法访问了Se
问题内容: 尝试从中的响应获取SSL证书。 什么是这样做的好方法? 问题答案: 故意包装这样的低级内容。通常,您唯一要做的就是验证证书是否有效。为此,只需通过即可。如果要使用非标准的cacert捆绑包,也可以通过。例如: 另外,主要是围绕其他库的一组包装器,主要是stdlib的(或对于2.x而言)和。 有时候,答案是只是为了获得在较低级别的对象(例如,是),但在许多情况下,这是不可能的。 这就是其
下面的链接介绍了如何为Java7的安全邮件证书创建jssecacerts http://infposs.blogspot.com/2013/06/installcert-and-java-7.html 但是,一旦我试图发送邮件异常给作为"java.security.cert.证书异常:没有主题替代名称存在..." 如果我没有错,新的jssecacerts证书文件应该保存在工作目录下,我们必须手动将
我正尝试仅使用.NET代码创建证书请求,并将该请求提交给我们的前提Active Directory PKI证书颁发机构,然后取回证书。我有一个已经工作了几年的解决方案,但它使用了CERTCLILib和CERTENROLLLib,我希望摆脱这些依赖关系,并将此代码移植到.NET5。 然后将这些证书导入到Yubikey设备上。我们在Yubikey上生成密钥对,然后将公钥与CSR一起使用。 这里的问题使