我正在尝试使用 Java 实现 RSA-OAEP 加密。我知道这需要一个默认为空字符串的标签。如何更改标签的值并使用内置类提供我选择的值?
最佳答案
正如我在评论中建议的,您需要使用 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));
}
顺便说一句,上面当然使用了 import static StandardCharsets.US_ASCII;
以防您的 IDE 不知道如何找到它。
请注意,PKCS#1 似乎只允许空(八位字节)字符串作为标签,其他人在 PKCS#1 v2.2 范围之外使用它:
encryption operations of RSAES-OAEP take the value of a label
L
as input. In this version of PKCS #1,L
is the empty string; other uses of the label are outside the scope of this document.
因此,使用除空字符串之外的任何 L
都会使您超出 OAEP 的标准使用范围,并且您必须自己显式定义此类用法。如果您有某种标识符,则最好将其编码为明文消息,因为库可能不提供对空字符串以外的标签的支持。
最后,关于术语的使用方式和实际 ASN.1 定义的一些细节:
pSourceAlgorithm
identifies the source (and possibly the value) of the labelL
. It SHALL be an algorithm ID with an OID in the setPKCS1PSourceAlgorithms
, which for this version SHALL consist ofid-pSpecified
, indicating that the label is specified explicitly. The parameters field associated withid-pSpecified
SHALL have a value of typeOCTET STRING
, containing the label. In previous versions of this specification, the term "encoding parameters" was used rather than "label", hence the name of the type below.
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
引用为单独的变量。
关于java - 使用 Java 为 RSA-OAEP 加密中的标签提供值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59487777/