提问人:Abraham 提问时间:10/15/2023 最后编辑:Abraham 更新时间:10/16/2023 访问量:127
如何使用 BouncyCastle C 向 CSR 添加主题可选名称 (SAN)#
How to add Subject Alternative Name (SAN) To a CSR Using BouncyCastle C#
问:
我正在尝试使用 C# 中的 BouncyCastle 库生成证书签名请求 (CSR)。我的目标是在 CSR 中包含主题替代名称,但我遇到了与扩展格式相关的错误。具体来说,我正在尝试传递一个Dictionary<DerObjectIdentifier, X509Extension>
作为构造函数的扩展,但它需要一个 .Pkcs10CertificationRequest
Asn1Set
解码 CSR 时,它应如下所示:
CSR详细信息
Certificate Request:
Data:
Version: 1 (0x0)
Subject: C=SA, OU=amman Branchch, O=haya yag 3, CN=127.0.0.1
Subject Public Key Info:
Public Key Algorithm: id-ecPublicKey
Public-Key: (256 bit)
pub:
04:db:8a:b6:27:ff:2b:ff:3a:c1:e1:16:53:0f:bc:
57:11:c4:8d:e7:b6:e9:35:8b:0b:62:94:d6:2e:57:
6f:bd:e6:49:c3:02:c8:5b:e4:e1:6c:21:80:87:a3:
f9:0b:d3:42:af:c4:bb:38:fa:cf:ab:d6:0f:2f:a9:
48:29:a2:4f:17
ASN1 OID: secp256k1
Attributes:
Requested Extensions:
1.3.6.1.4.1.311.20.2:
..TSTZATCA-Code-Signing
X509v3 Subject Alternative Name:
DirName:/SN=1-haya|2-234|3-354/UID=310175397400003/title=1100/registeredAddress=Zatca 3/businessCategory=Food Bussiness3
Signature Algorithm: ecdsa-with-SHA256
Signature Value:
30:44:02:20:2a:eb:3b:b9:8a:e9:57:ba:30:d6:fe:25:22:05:
0d:ff:80:17:6f:23:59:f2:1a:dc:7c:3d:69:71:94:f7:f2:67:
02:20:2b:26:95:2c:1f:18:13:93:c9:0f:7b:83:c9:b0:84:db:
21:ac:92:c8:7b:f3:7e:9b:6a:10:c7:c3:8f:b3:fb:6b
(Decoded using the following version of OpenSSL: OpenSSL 3.1.1 30 May 2023)
CSR ASN.1 信息
0 459: SEQUENCE {
4 370: SEQUENCE {
8 1: INTEGER 0
11 79: SEQUENCE {
13 11: SET {
15 9: SEQUENCE {
17 3: OBJECT IDENTIFIER countryName (2 5 4 6)
22 2: PrintableString 'SA'
: }
: }
26 23: SET {
28 21: SEQUENCE {
30 3: OBJECT IDENTIFIER organizationalUnitName (2 5 4 11)
35 14: UTF8String 'amman Branchch'
: }
: }
51 19: SET {
53 17: SEQUENCE {
55 3: OBJECT IDENTIFIER organizationName (2 5 4 10)
60 10: UTF8String 'haya yag 3'
: }
: }
72 18: SET {
74 16: SEQUENCE {
76 3: OBJECT IDENTIFIER commonName (2 5 4 3)
81 9: UTF8String '127.0.0.1'
: }
: }
: }
92 86: SEQUENCE {
94 16: SEQUENCE {
96 7: OBJECT IDENTIFIER ecPublicKey (1 2 840 10045 2 1)
105 5: OBJECT IDENTIFIER secp256k1 (1 3 132 0 10)
: }
112 66: BIT STRING
: 04 DB 8A B6 27 FF 2B FF 3A C1 E1 16 53 0F BC 57
: 11 C4 8D E7 B6 E9 35 8B 0B 62 94 D6 2E 57 6F BD
: E6 49 C3 02 C8 5B E4 E1 6C 21 80 87 A3 F9 0B D3
: 42 AF C4 BB 38 FA CF AB D6 0F 2F A9 48 29 A2 4F
: 17
: }
180 195: [0] {
183 192: SEQUENCE {
186 9: OBJECT IDENTIFIER extensionRequest (1 2 840 113549 1 9 14)
197 178: SET {
200 175: SEQUENCE {
203 36: SEQUENCE {
205 9: OBJECT IDENTIFIER
: enrollCerttypeExtension (1 3 6 1 4 1 311 20 2)
216 23: OCTET STRING
: 13 15 54 53 54 5A 41 54 43 41 2D 43 6F 64 65 2D
: 53 69 67 6E 69 6E 67
: }
241 134: SEQUENCE {
244 3: OBJECT IDENTIFIER subjectAltName (2 5 29 17)
249 127: OCTET STRING
: 30 7D A4 7B 30 79 31 1B 30 19 06 03 55 04 04 0C
: 12 31 2D 68 61 79 61 7C 32 2D 32 33 34 7C 33 2D
: 33 35 34 31 1F 30 1D 06 0A 09 92 26 89 93 F2 2C
: 64 01 01 0C 0F 33 31 30 31 37 35 33 39 37 34 30
: 30 30 30 33 31 0D 30 0B 06 03 55 04 0C 0C 04 31
: 31 30 30 31 10 30 0E 06 03 55 04 1A 0C 07 5A 61
: 74 63 61 20 33 31 18 30 16 06 03 55 04 0F 0C 0F
: 46 6F 6F 64 20 42 75 73 73 69 6E 65 73 73 33
: }
: }
: }
: }
: }
: }
378 10: SEQUENCE {
380 8: OBJECT IDENTIFIER ecdsaWithSHA256 (1 2 840 10045 4 3 2)
: }
390 71: BIT STRING
: 30 44 02 20 2A EB 3B B9 8A E9 57 BA 30 D6 FE 25
: 22 05 0D FF 80 17 6F 23 59 F2 1A DC 7C 3D 69 71
: 94 F7 F2 67 02 20 2B 26 95 2C 1F 18 13 93 C9 0F
: 7B 83 C9 B0 84 DB 21 AC 92 C8 7B F3 7E 9B 6A 10
: C7 C3 8F B3 FB 6B
: }
您可以使用此 CSR 作为参考:
-----BEGIN CERTIFICATE REQUEST-----
MIIByzCCAXICAQAwTzELMAkGA1UEBhMCU0ExFzAVBgNVBAsMDmFtbWFuIEJyYW5j
aGNoMRMwEQYDVQQKDApoYXlhIHlhZyAzMRIwEAYDVQQDDAkxMjcuMC4wLjEwVjAQ
BgcqhkjOPQIBBgUrgQQACgNCAATbirYn/yv/OsHhFlMPvFcRxI3ntuk1iwtilNYu
V2+95knDAshb5OFsIYCHo/kL00KvxLs4+s+r1g8vqUgpok8XoIHDMIHABgkqhkiG
9w0BCQ4xgbIwga8wJAYJKwYBBAGCNxQCBBcTFVRTVFpBVENBLUNvZGUtU2lnbmlu
ZzCBhgYDVR0RBH8wfaR7MHkxGzAZBgNVBAQMEjEtaGF5YXwyLTIzNHwzLTM1NDEf
MB0GCgmSJomT8ixkAQEMDzMxMDE3NTM5NzQwMDAwMzENMAsGA1UEDAwEMTEwMDEQ
MA4GA1UEGgwHWmF0Y2EgMzEYMBYGA1UEDwwPRm9vZCBCdXNzaW5lc3MzMAoGCCqG
SM49BAMCA0cAMEQCICrrO7mK6Ve6MNb+JSIFDf+AF28jWfIa3Hw9aXGU9/JnAiAr
JpUsHxgTk8kPe4PJsITbIaySyHvzfptqEMfDj7P7aw==
-----END CERTIFICATE REQUEST-----
下面是相关代码:
public static string GeneratePkcs10ECDSA(string commonName, string organizationUnitName, string organizationName, string country, string sanDirName)
{
var csr = "";
try
{
// Create ECDSA key pair generator
var ecKeyPairGenerator = new ECKeyPairGenerator();
var genParam = new ECKeyGenerationParameters(SecObjectIdentifiers.SecP256k1, new SecureRandom());
ecKeyPairGenerator.Init(genParam);
AsymmetricCipherKeyPair pair = ecKeyPairGenerator.GenerateKeyPair();
AsymmetricCipherKeyPair ecKeyPair = ecKeyPairGenerator.GenerateKeyPair();
// Subject Name
var subjectAttrs = new List<DerObjectIdentifier>();
var subjectValues = new List<string>();
subjectAttrs.Add(X509Name.C);
subjectValues.Add(country);
subjectAttrs.Add(X509Name.OU);
subjectValues.Add(organizationUnitName);
subjectAttrs.Add(X509Name.O);
subjectValues.Add(organizationName);
subjectAttrs.Add(X509Name.CN);
subjectValues.Add(commonName);
var subject = new X509Name(subjectAttrs.ToArray(), subjectValues.ToArray());
// Subject Alternative Names
var sanAttrs = new List<DerObjectIdentifier>();
var sanValues = new List<string>();
sanAttrs.Add(X509Name.BusinessCategory);
sanValues.Add("Examp");
sanAttrs.Add(X509Name.PostalAddress);
sanValues.Add("Examp 1");
sanAttrs.Add(X509Name.T);
sanValues.Add("1100");
sanAttrs.Add(X509Name.UID);
sanValues.Add("31047539761234");
sanAttrs.Add(X509Name.SerialNumber);
sanValues.Add("1-qwer|2-322|3-123");
var san = new X509Name(sanAttrs.ToArray(), sanValues.ToArray());
string certificateTemplateName = "1.3.6.1.4.1.311.20.2";
DerObjectIdentifier certificateTemplateExtensionOid = new DerObjectIdentifier(certificateTemplateName);
DerSequence certificateTemplateExtension = new DerSequence(new DerObjectIdentifier(certificateTemplateName), new DerPrintableString("ZATCA-Code-Signing"));
var extensions = new Dictionary<DerObjectIdentifier, X509Extension>()
{
{
X509Extensions.BasicConstraints,
new X509Extension(true, new DerOctetString(new BasicConstraints(false)))
},
{
X509Extensions.KeyUsage,
new X509Extension(true, new DerOctetString(new KeyUsage(KeyUsage.DigitalSignature | KeyUsage.KeyEncipherment | KeyUsage.NonRepudiation)))
},
{
X509Extensions.SubjectAlternativeName,
new X509Extension(false, new DerOctetString(new GeneralName(GeneralName.DirectoryName, san)))
},
{
certificateTemplateExtensionOid,
new X509Extension(false, new DerOctetString(certificateTemplateExtension))
},
};
// Convert extensions to Asn1Set
var extensionList = new List<Asn1Encodable>();
foreach (var extension in extensions)
{
extensionList.Add(extension.Value.GetParsedValue());
}
// Convert the list of extensions to an Asn1Set
var extensionsSet = new DerSet(extensionList.ToArray());
var pkcs10CertificationRequest = new Pkcs10CertificationRequest(
"SHA256withECDSA",
subject,
ecKeyPair.Public,
extensionsSet,
ecKeyPair.Private);
csr = Convert.ToBase64String(pkcs10CertificationRequest.GetEncoded());
return csr;
}
catch (Exception ex)
{
// Handle errors as needed
throw new Exception(ex.Message);
}
}
我收到此错误:
System.Exception: 'Unknown object in factory: Org.BouncyCastle.Asn1.DerBitString (Parameter 'obj')'
由于我之前没有任何加密经验,我不确定我是否正确地处理了这一点。我一直在尝试找到解决这个问题的方法,但我不确定该怎么做,任何指导或示例将不胜感激。
谢谢你的帮助。
答:
1赞
Topaco
10/16/2023
#1
以下代码生成与发布的 CSR 相同的 CSR(新生成的密钥除外,因此是签名):
...
// Create ECDSA key pair generator
var ecKeyPairGenerator = new ECKeyPairGenerator();
var genParam = new ECKeyGenerationParameters(SecObjectIdentifiers.SecP256k1, new SecureRandom());
ecKeyPairGenerator.Init(genParam);
AsymmetricCipherKeyPair ecKeyPair = ecKeyPairGenerator.GenerateKeyPair();
// Subject Name
var subjectAttrs = new List<DerObjectIdentifier>() { X509Name.C, X509Name.OU, X509Name.O, X509Name.CN };
var subjectValues = new List<string>() { country, organizationUnitName, organizationName, commonName };
var subject = new X509Name(subjectAttrs.ToArray(), subjectValues.ToArray());
// SAN
var sanAttrs = new List<DerObjectIdentifier>() { X509Name.Surname, X509Name.UID, X509Name.T, new DerObjectIdentifier("2.5.4.26"), X509Name.BusinessCategory};
var sanValues = new List<string>() { "1-haya|2-234|3-354", "310175397400003", "1100", "Zatca 3", "Food Bussiness3" };
var san = new X509Name(sanAttrs.ToArray(), sanValues.ToArray());
// Extensions
var extensionsDictionary = new Dictionary<DerObjectIdentifier, X509Extension>()
{
{
new DerObjectIdentifier("1.3.6.1.4.1.311.20.2"),
new X509Extension(false, new DerOctetString(new DerPrintableString("TSTZATCA-Code-Signing")))
},
{
X509Extensions.SubjectAlternativeName,
new X509Extension(false, new DerOctetString(new DerSequence(new DerTaggedObject(4, san))))
},
};
var extensions = new X509Extensions(extensionsDictionary);
var attribute = new AttributePkcs(PkcsObjectIdentifiers.Pkcs9AtExtensionRequest, new DerSet(extensions));
var extensionsSet = new DerSet(attribute);
// Create CSR using keys, subject, extensions
var pkcs10CertificationRequest = new Pkcs10CertificationRequest(
"SHA256withECDSA",
subject,
ecKeyPair.Public,
extensionsSet,
ecKeyPair.Private);
var csr = Convert.ToBase64String(pkcs10CertificationRequest.GetEncoded());
...
此代码基于您的代码。与原始代码的主要区别在于“扩展”部分:
- 这两个字典元素创建 和 序列。
enrollCerttypeExtension
subjectAltName
- 第二个字典元素的代码使用 SAN 元素创建 OCTET STRING - SEQUENCE - [4] - SEQUENCE 结构。
new DerOctetString(new DerSequence(new DerTaggedObject(4, san)))
有关ASN.1的概述,请参阅此处。
如果生成的CSR加载到ASN.1解析器(例如 https://lapo.it/asn1js)中,则会为extensions-part显示以下ASN.1:
根据已发布的 CSR 的扩展 ASN.1 部分,可以在此处使用 lapo.it 解析器进行验证。
评论
1赞
Topaco
10/16/2023
在线运行固定代码:dotnetfiddle.net/BqDFVV
0赞
Abraham
10/16/2023
谢谢你的帮助!,ASN.1资源我一定会通过它
1赞
Topaco
10/16/2023
@Abraham - 解释一下你为什么撤消接受会很好。
1赞
Abraham
10/16/2023
对不起,我不知道我这样做了,谢谢你让我知道。
评论