我正在尝试使用Java实现RSA-OAEP加密。我了解这需要标签,默认情况下为空字符串。如何使用内置类更改label的值并提供选择的值?
答案 0 :(得分:2)
正如我在评论中建议的那样,您需要使用PSource.PSpecified
构造函数。
单词的选择,尤其是变量P
(in the PKCS#1 specifications anywhere 不存在)使用户陷入ASN.1 specifications领域的术语泥潭,不是您想成为的地方。
我已经得出结论,Java设计人员/开发人员的意思是id-pSpecified
,其中P
是EncodedParameters
,这是“标签”一词的旧世界。反过来,这意味着构造函数PSource.PSpecified
可用于指示(字符编码)标签。因此,尽管“标签”一词可能表示一个字符串,但在密码学领域却并非如此。您将必须自己执行某种字符转换,如果要使用文本标签,则应记录此字符编码。
// generate a relatively small key for testing
KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
kpg.initialize(2048);
KeyPair kp = kpg.generateKeyPair();
// OAEP spec with label
OAEPParameterSpec spec = new OAEPParameterSpec("SHA-1", "MGF1", MGF1ParameterSpec.SHA1,
new PSource.PSpecified("label".getBytes(US_ASCII)));
// OAEP spec without label
OAEPParameterSpec specEmpty = new OAEPParameterSpec("SHA-1", "MGF1", MGF1ParameterSpec.SHA1,
PSource.PSpecified.DEFAULT);
byte[] ct;
{
// encrypt to ciphertext using label
Cipher rsaOAEPEnc = Cipher.getInstance("RSA/ECB/OAEPPadding");
rsaOAEPEnc.init(Cipher.ENCRYPT_MODE, kp.getPublic(), spec);
ct = rsaOAEPEnc.doFinal("owlstead".getBytes(US_ASCII));
}
{
// decrypt with label
Cipher rsaOAEPDec = Cipher.getInstance("RSA/ECB/OAEPPadding");
rsaOAEPDec.init(Cipher.DECRYPT_MODE, kp.getPrivate(), spec);
byte[] pt = rsaOAEPDec.doFinal(ct);
System.out.println(new String(pt, US_ASCII));
}
{
// decrypt without label (fails with an exception)
Cipher rsaOAEPDec = Cipher.getInstance("RSA/ECB/OAEPPadding");
rsaOAEPDec.init(Cipher.DECRYPT_MODE, kp.getPrivate(), specEmpty);
byte[] pt = rsaOAEPDec.doFinal(ct);
System.out.println(new String(pt, US_ASCII));
}
顺便说一句,如果您的IDE不知道如何找到它,以上当然会使用import static StandardCharsets.US_ASCII;
。
请注意,PKCS#1似乎只允许使用空(八位字节)字符串作为标签,其他人可以在
RSAES-OAEP的加密操作 标签
L
的值作为输入。在此版本的PKCS#1中,L
是 空字符串;标签的其他用途不在 该文件。
因此,使用除空字符串以外的任何L
都会使您超出OAEP的标准用法,并且必须自己明确定义此类用法。如果您有某种标识符,则最好将其编码为纯文本消息,因为库可能不支持空字符串以外的标签。
最后,对术语的使用方式和实际ASN.1定义进行了一些细化:
pSourceAlgorithm
标识源(可能还有值) 标签L
。它应该是一个算法ID,在集合中具有OIDPKCS1PSourceAlgorithms
,此版本应包含id-pSpecified
,表示已明确指定标签。 与id-pSpecified
关联的参数字段应具有一个 类型OCTET STRING
的值,包含标签。在以前 在本规范的版本中,术语“编码参数”为 使用而不是“标签”,因此是以下类型的名称。PSourceAlgorithm ::= AlgorithmIdentifier { {PKCS1PSourceAlgorithms} } PKCS1PSourceAlgorithms ALGORITHM-IDENTIFIER ::= { { OID id-pSpecified PARAMETERS EncodingParameters }, ... -- Allows for future expansion -- } id-pSpecified OBJECT IDENTIFIER ::= { pkcs-1 9 } EncodingParameters ::= OCTET STRING(SIZE(0..MAX))
这在很大程度上解释了Java规范的发展。如果您在阅读规范后将它们视为它们,那么它们实际上很有意义-除了在规范中将P
称为单独变量之外。