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

问题描述 投票:2回答:1

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

java cryptography rsa public-key-encryption
1个回答
1
投票

正如我在评论中所建议的,您需要使用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似乎只允许使用空(八位字节)字符串作为标签,其他使用它超出PKCS#1 v2.2的范围]:

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称为单独变量之外。

© www.soinside.com 2019 - 2024. All rights reserved.