使用 Java 为 RSA-OAEP 加密中的标签提供价值

Providing value for label in RSA- OAEP encryption using Java

我正在尝试使用 Java 实施 RSA-OAEP 加密。我知道这需要一个默认为空字符串的标签。如何使用内置 class?

更改标签的值并提供我选择的值

正如我在评论中所建议的,您需要使用 PSource.PSpecified 构造函数。

单词的选择,尤其是变量P 不存在in the PKCS#1 specifications anywhere leads the user into a quagmire of terms in the world of 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 label L. It SHALL be an algorithm ID with an OID in the set PKCS1PSourceAlgorithms, which for this version SHALL consist of id-pSpecified, indicating that the label is specified explicitly. The parameters field associated with id-pSpecified SHALL have a value of type OCTET 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 称为单独的变量。