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

时间:2019-12-26 11:27:18

标签: java cryptography rsa public-key-encryption

我正在尝试使用Java实现RSA-OAEP加密。我了解这需要标签,默认情况下为空字符串。如何使用内置类更改label的值并提供选择的值?

1 个答案:

答案 0 :(得分:2)

正如我在评论中建议的那样,您需要使用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));
}

顺便说一句,如果您的IDE不知道如何找到它,以上当然会使用import static StandardCharsets.US_ASCII;


请注意,PKCS#1似乎只允许使用空(八位字节)字符串作为标签,其他人可以在 PKCS#1 v2.2的范围之外使用它:

  RSAES-OAEP的

加密操作      标签L的值作为输入。在此版本的PKCS#1中,L是      空字符串;标签的其他用途不在      该文件。

因此,使用除空字符串以外的任何L都会使您超出OAEP的标准用法,并且必须自己明确定义此类用法。如果您有某种标识符,则最好将其编码为纯文本消息,因为库可能不支持空字符串以外的标签。


最后,对术语的使用方式和实际ASN.1定义进行了一些细化:

  

pSourceAlgorithm标识源(可能还有值)         标签L。它应该是一个算法ID,在集合中具有OID         PKCS1PSourceAlgorithms,此版本应包含         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称为单独变量之外。