C# SubjectAlternativeName中的非ASCII字符

C# SubjectAlternativeName中的非ASCII字符,c#,bouncycastle,C#,Bouncycastle,我正在尝试使用BouncyCastle.NET创建自签名X509证书。它似乎在一般情况下起作用,但对于包含非ASCII字符的国际化域名,我失败了 下面是我正在做的一个简洁的例子。“myDevice.abc.example.com”的单元测试用例成功,但对于包含非ASCII字符的其他用例(如“myDevice.abc.example.com”)则失败 最终断言失败,从证书检索的字符串中的特殊字符将替换为“?” 这应该有效吗?我是否犯了明显的错误?多亏了作者的评论,我找到了答案:在创建通用名之前,域

我正在尝试使用
BouncyCastle.NET
创建自签名X509证书。它似乎在一般情况下起作用,但对于包含非ASCII字符的国际化域名,我失败了

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

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

这应该有效吗?我是否犯了明显的错误?

多亏了作者的评论,我找到了答案:在创建通用名之前,域名必须按照以下内容进行编码:

var idn = new System.Globalization.IdnMapping();
idn.UseStd3AsciiRules = true;
idn.AllowUnassigned = false;
string encodedFqdn = idn.GetAscii(fqdn);
var dnsName = new GeneralName(GeneralName.DnsName, encodedFqdn);
显然,它必须在读取证书后解码:

var actualEncodedFqdn = generalName[1];
var actual = idn.GetUnicode(actualEncodedFqdn.ToString());
StringAssert.AreEqualIgnoringCase(fqdn, actual);

当fqdn进入测试时,您是否尝试过调试它?然后还检查
dnsName
然后
subjectAltName
然后
san
然后
generalName
?基本上,您试图缩小到哪一行代码破坏了其中一个值。然后您可以将问题中的代码缩短为这些行。字符串在certGenerator之前(包括certGenerator)的调试器中看起来很好。当我从x509Certificate检索回san时,我提取了generalName,不再看到特殊字符。那么,您能否将示例代码缩短到这些行?调试
newgeneralname(int标记,字符串名)
的构造函数中正在创建的内容会很好:这里有一个指向。它可以是:
DerIA5String
DerObjectIdentifier
X509Name
DerOctetString
,以确定是否接受特殊字符。在
DerIA5String
中,有一个可选的验证,它使用以下命令检查字符串是否有效:
foreach(char-ch-In-str){if(ch>0x007f){return false;
。这意味着127以上的任何内容都是无效的,即不是ASCII。我故意使示例尽可能小,但仍然完整(例如:代码应该可以按原样执行)。我已经查看了GeneralName构造函数的源代码;在我的示例的两行注释中,我尝试使用显式验证实例化DerIA5STring。对于非ASCII字符,验证失败。也许这意味着我应该在创建GeneralName之前转义fqdn?但根据什么格式转义?(顺便说一句:谢谢你的帮助!)
var actualEncodedFqdn = generalName[1];
var actual = idn.GetUnicode(actualEncodedFqdn.ToString());
StringAssert.AreEqualIgnoringCase(fqdn, actual);