我正在尝试解密 S/MIME 电子邮件(最初通过 Outlook 发送),为此,我使用了 bouncycaSTLe API。不过,我遇到了麻烦。
我在 Windows 证书存储中有收件人的证书。我之前用它给对方发送了一封签名加密的邮件,对方又用它给我发了一封加密的回复。然后,我将证书(带有私钥)导出为 .pfx 文件,并将此 pfx 文件加载到 Java KeyStore 中。但是,它不起作用,我怀疑这是因为主题 key 标识符不匹配。
这是我用来从 KeyStore 获取主题 key ID 的代码:
KeyStore ks = KeyStore.getInstance("PKCS12");
char[] pw = "password".toCharArray();
ks.load(new FileInputStream("d:\\cert_priv_key.pfx"), pw);
Enumeration en = ks.aliases();
while( en.hasMoreElements() )
{
String alias = (String)en.nextElement();
System.out.println(alias);
if( ks.isKeyEntry(alias) )
{
Certificate[] chain = ks.getCertificateChain(alias);
X509Certificate cert = (X509Certificate)chain[0];
byte[] id = cert.getExtensionValue("2.5.29.14");
System.out.println(" " + toHex(id));
}
}
这会打印出以下 key 标识符:
04 16 04 14 88 ed bb 7c 64 7b 41 63 48 0a 24 40 2b 3c d0 78 72 3c 30 b3
但是,当我检查 Windows 证书存储时, key 标识符不同:
88 ed bb 7c 64 7b 41 63 48 0a 24 40 2b 3c d0 78 72 3c 30 b3
KeyStore 在前面返回额外的 4 个字节(主题 key 标识符应该是 key 的 160 位 SHA1 哈希值,因此长 20 个字节,对吗?)。
更令人困惑的是,当我使用 bouncycaSTLe API 解析 S/MIME 电子邮件并检查收件人 (SMIMEEnveloped.getRecipientInfos().getRecipients()) 时,唯一的收件人返回(应该只有一个)具有此主题 key 标识符:
04 14 88 ed bb 7c 64 7b 41 63 48 0a 24 40 2b 3c d0 78 72 3c 30 b3
...它只有两个额外的字节,而不是四个,我想这就是我无法用证书解密电子邮件的原因。
为什么这些主题键标识符都不匹配?我做错了什么?
最佳答案
如果您了解所有规范,所有这些答案都是一致的,但当然,如果您不了解,这意味着它们会令人困惑。首先要看的地方是RFC 5280, section 4.2.1.2 .在这种情况下,使用方法 (1)。接下来看section A.2在 KeyIdentifier 的定义处。它被定义为 OCTET STRING。现在看看一个 ASN.1 OCTET STRING should be encoded 是如何产生的.它应该以十六进制 04 开头,后跟以字节为单位的长度(20 个字节,或 14 个十六进制),然后是实际的八位字节字符串(SHA1 哈希)。所以扩展的内容应该是
04 14 88 ed bb 7c 64 7b 41 63 48 0a 24 40 2b 3c d0 78 72 3c 30 b3
最后看一下Extension的ASN.1定义.它表示扩展值必须编码为 OCTET STRING。在这个特定扩展的情况下,最终效果是连续两次编码为 OCTET STRING。在这一层 OCTET STRING 是前一个 OCTET STRING,它包括两个头字节 04 14,所以长度是十六进制 16,编码是
04 16 04 14 88 ed bb 7c 64 7b 41 63 48 0a 24 40 2b 3c d0 78 72 3c 30 b3
这是 X509Extension.getExtensionValue() 返回的值方法。现在, key ID 中有趣的部分只是以 88 开头的 SHA1 哈希,因此这就是 Windows 实用程序显示的内容。显然,您使用的 bouncycaSTLe 方法显示了扩展名而没有进行额外的解码。
关于java - 为什么我的 key 标识符不匹配?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6523081/
类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc
我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co
我正在使用的第三方API的文档状态:"[O]urAPIonlyacceptspaddedBase64encodedstrings."什么是“填充的Base64编码字符串”以及如何在Ruby中生成它们。下面的代码是我第一次尝试创建转换为Base64的JSON格式数据。xa=Base64.encode64(a.to_json) 最佳答案 他们说的padding其实就是Base64本身的一部分。它是末尾的“=”和“==”。Base64将3个字节的数据包编码为4个编码字符。所以如果你的输入数据有长度n和n%3=1=>"=="末尾用于填充n%
我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i
为什么4.1%2返回0.0999999999999996?但是4.2%2==0.2。 最佳答案 参见此处:WhatEveryProgrammerShouldKnowAboutFloating-PointArithmetic实数是无限的。计算机使用的位数有限(今天是32位、64位)。因此计算机进行的浮点运算不能代表所有的实数。0.1是这些数字之一。请注意,这不是与Ruby相关的问题,而是与所有编程语言相关的问题,因为它来自计算机表示实数的方式。 关于ruby-为什么4.1%2使用Ruby返
在我的应用程序中,我需要能够找到所有数字子字符串,然后扫描每个子字符串,找到第一个匹配范围(例如5到15之间)的子字符串,并将该实例替换为另一个字符串“X”。我的测试字符串s="1foo100bar10gee1"我的初始模式是1个或多个数字的任何字符串,例如,re=Regexp.new(/\d+/)matches=s.scan(re)给出["1","100","10","1"]如果我想用“X”替换第N个匹配项,并且只替换第N个匹配项,我该怎么做?例如,如果我想替换第三个匹配项“10”(匹配项[2]),我不能只说s[matches[2]]="X"因为它做了两次替换“1fooX0barXg
如何匹配未被反斜杠转义的平衡定界符对(其本身未被反斜杠转义)(无需考虑嵌套)?例如对于反引号,我试过了,但是转义的反引号没有像转义那样工作。regex=/(?!$1:"how\\"#expected"how\\`are"上面的正则表达式不考虑由反斜杠转义并位于反引号前面的反斜杠,但我愿意考虑。StackOverflow如何做到这一点?这样做的目的并不复杂。我有文档文本,其中包括内联代码的反引号,就像StackOverflow一样,我想在HTML文件中显示它,内联代码用一些spanMaterial装饰。不会有嵌套,但转义反引号或转义反斜杠可能出现在任何地方。
它不等于主线程的binding,这个toplevel作用域是什么?此作用域与主线程中的binding有何不同?>ruby-e'putsTOPLEVEL_BINDING===binding'false 最佳答案 事实是,TOPLEVEL_BINDING始终引用Binding的预定义全局实例,而Kernel#binding创建的新实例>Binding每次封装当前执行上下文。在顶层,它们都包含相同的绑定(bind),但它们不是同一个对象,您无法使用==或===测试它们的绑定(bind)相等性。putsTOPLEVEL_BINDINGput
我可以得到Infinity和NaNn=9.0/0#=>Infinityn.class#=>Floatm=0/0.0#=>NaNm.class#=>Float但是当我想直接访问Infinity或NaN时:Infinity#=>uninitializedconstantInfinity(NameError)NaN#=>uninitializedconstantNaN(NameError)什么是Infinity和NaN?它们是对象、关键字还是其他东西? 最佳答案 您看到打印为Infinity和NaN的只是Float类的两个特殊实例的字符串
如果您尝试在Ruby中的nil对象上调用方法,则会出现NoMethodError异常并显示消息:"undefinedmethod‘...’fornil:NilClass"然而,有一个tryRails中的方法,如果它被发送到一个nil对象,它只返回nil:require'rubygems'require'active_support/all'nil.try(:nonexisting_method)#noNoMethodErrorexceptionanymore那么try如何在内部工作以防止该异常? 最佳答案 像Ruby中的所有其他对象