java openssl X509_SIG结构和编码/解码功能

问题描述

我正在尝试在Java中使用C语言编写的使用openssl C API RSA_sign函数的签名算法。 此函数不加密数据,而是将数据放入带有某些元数据的X509_SIG结构中,使用i2d_X509_SIG openssl函数对结构进行编码,然后最终对编码结果进行加密。 有没有一种方法可以重现这种用Java签名数据的方法?一些Java库中是否存在X509_SIG结构和编码/解码功能? 码

解决方法

您误解了(或误解了)RSA_sign的作用。

忽略某些不适用于此处的特殊情况,它实现了最初在PKCS1 v1中定义为“类型1”的RSA签名方案,现在在PKCS1 v2中保留为RSASSA-PKCS1-v1_5(即带有v1附录的RSA签名方案) .5 PKCS1);请参见rfc8017的section 8.2section 9.2,以及section 5.2中的相关原语。要签名(或RFC更正式地声明它,以生成签名),这将按顺序有效地执行以下操作:

E1。散列邮件

E2。将哈希值加上哈希算法的算法标识符编码为DER中的ASN.1结构DigestInfo;由于DER的工作方式,这等效于添加第9.2节的注释中所述的固定前缀。

E3-5。垫有00 01 FF ...(根据需要,但至少为8)00

G2。将八位位组字符串转换为数字,应用原始RSASP1(使用私有指数进行模幂运算),然后将(新)数字转换回正确大小的八位位组字符串。从历史上看,在一代人之前,有时将其描述为“使用私钥加密”,而将RSAVP1称为“使用公钥解密”,尽管这在语义上是错误的,因为signing is not encryption,并且很快发现这种混乱导致不良的系统设计容易受到攻击和损坏,因此在本世纪,我们将其称为签名和验证。

RSA_sign要求调用者执行哈希步骤(E1)。然后,它使用encode_pkcs1来命名标准X509_SIG的结构,调用DigestInfo来执行步骤E2。然后调用RSA_private_encrypt来执行E3-5和G2;之所以这样命名,是因为OpenSSL源自几十年前写的SSLeay,当时人们对“签名就是向后加密”的困惑仍然很普遍。

此签名方案是(1)标准和(2)很常见,并且以Java加密方式实现-包括标准要求的哈希步骤,与OpenSSL RSA_sign的DigestInfo步骤不同。请参见https://docs.oracle.com/en/java/javase/11/docs/specs/security/standard-names.html#signature-algorithms中的java.security.Signature算法名称(方案){SHA1,SHA256,etc}withRSA