首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >SubjectAlternativeName中的非ASCII字符

问SubjectAlternativeName中的非ASCII字符
EN

Stack Overflow用户
提问于 2018-01-26 13:31:46
回答 1查看 381关注 0票数 1

我正在尝试使用self-signed X509 certificates创建BouncyCastle.NET。这似乎在一般的工作,但我失败的国际化域名,其中包含非ASCII字符。

下面是我正在做的事情的一个简洁的例子。"myDevice.abc.example.com“的单元测试用例成功,但对于包含non-ASCII字符(如"myDevice.äöü.example.com")的其他情况则失败。

代码语言:javascript
复制
[TestCase("myDevice.abc.example.com")]
[TestCase("myDevice.äöü.example.com")]  // western european
[TestCase("myDevice.ařa.example.com")]  // eastern european
[TestCase("mydevice.aデa.example.com")] // katakana
[Test]
public void IdnTest(string fqdn)
{
    #region Preparation
    ECKeyPairGenerator kpgen = new ECKeyPairGenerator();
    kpgen.Init(new KeyGenerationParameters(new SecureRandom(new CryptoApiRandomGenerator()), Constants.SelectedRootKeySize));
    var caKeyPair = kpgen.GenerateKeyPair();
    var certKeyPair = kpgen.GenerateKeyPair();
    X509V3CertificateGenerator certGenerator = new X509V3CertificateGenerator();
    certGenerator.SetSerialNumber(Org.BouncyCastle.Math.BigInteger.ProbablePrime(120, new Random()));
    IList oids = new ArrayList() { X509Name.OU };
    IList values = new ArrayList() { "Test" };
    certGenerator.SetIssuerDN(new X509Name(oids, values));
    certGenerator.SetNotBefore(DateTime.Now.Date);
    certGenerator.SetNotAfter(DateTime.Now + TimeSpan.FromDays(365));
    certGenerator.SetPublicKey(certKeyPair.Public);

    //var dnsString = new Org.BouncyCastle.Asn1.DerIA5String(fqdn, true);   //explicit validation would fail here
    //var dnsName = new GeneralName(dnsString, GeneralName.DnsName);
    var dnsName = new GeneralName(GeneralName.DnsName, fqdn);               //here I can create an GeneralName without validation failure
    GeneralNames subjectAltName = new GeneralNames(dnsName);
    certGenerator.AddExtension(X509Extensions.SubjectAlternativeName, true, subjectAltName);

    ISignatureFactory signatureFactory = new Asn1SignatureFactory("sha256WithECDSA", caKeyPair.Private, new SecureRandom(new CryptoApiRandomGenerator()));
    Org.BouncyCastle.X509.X509Certificate x509Certificate = certGenerator.Generate(signatureFactory);
    #endregion

    #region Verification
    var san = x509Certificate.GetSubjectAlternativeNames() as ArrayList;
    Assert.AreEqual(1, san.Count);
    var generalName = san[0] as System.Collections.ArrayList;
    Assert.AreEqual(GeneralName.DnsName, generalName[0]);
    object actual = generalName[1];
    Assert.AreEqual(fqdn, actual);
    #endregion
}

最后的断言失败,从证书中检索到的字符串中的特殊字符将被“?”替换。

这是不是该起作用的东西,我是不是做错了什么?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-01-29 07:31:36

感谢DJDaveMark和詹姆斯·K·波尔克的评论,我找到了答案:在创建GeneralName之前,必须根据rfc 5280对域名进行编码:

代码语言:javascript
复制
var idn = new System.Globalization.IdnMapping();
idn.UseStd3AsciiRules = true;
idn.AllowUnassigned = false;
string encodedFqdn = idn.GetAscii(fqdn);
var dnsName = new GeneralName(GeneralName.DnsName, encodedFqdn);

显然,它必须在阅读证书后被解码:

代码语言:javascript
复制
var actualEncodedFqdn = generalName[1];
var actual = idn.GetUnicode(actualEncodedFqdn.ToString());
StringAssert.AreEqualIgnoringCase(fqdn, actual);
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/48462339

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档