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

标签 java cryptography rsa public-key-encryption

我正在尝试使用 Java 实现 RSA-OAEP 加密。我知道这需要一个默认为空字符串的标签。如何更改标签的值并使用内置类提供我选择的值?

最佳答案

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

单词的选择,尤其是不存在的变量P in the PKCS#1 specifications anywhere 带领用户陷入 ASN.1 specifications 世界中的术语泥潭,不是您想去的地方。

我得出的结论是,Java 设计者/开发人员的意思是 id-pSpecified,其中 PEncodedParameters,这是旧世界对于术语“标签”。这反过来意味着构造函数 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 引用为单独的变量。

关于java - 使用 Java 为 RSA-OAEP 加密中的标签提供值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59487777/

相关文章:

java - 如果大部分方法在调用站点都是死代码,java 可以内联一个大方法吗?

java - 由于 Jenkins 中的 "incompatible types"错误,无法将 java.util.List<java.lang.Object> 转换为 java.util.List<java.nio.file.Path>

java - 调用我创建的方法来减少变量的值不会对该值产生影响。我该如何解决这个问题?

cryptography - 通过套接字发送公钥的安全方法

javascript - 如何使用 CryptoJS 使用 AES 算法加密文件?

java - 将递归连接转换为java对象

javascript - Objective-C 中的渐进式 HMAC SHA256

openssl - 这个命令有什么作用? "openssl genrsa -aes256 -out example.key 2048"

PHP shell_exec 使用 ssh 运行 shell 脚本

cryptography - 使用 openssl.exe 使用 256 位 RSA key 签名 20 字节消息,但不在代码中