Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Providing value for label in RSA- OAEP encryption using Java

I am trying to implement RSA-OAEP encryption using Java. I understand that this requires a label which is by default an empty string. How do I change the value of label and provide a value of my choice using the built in class?

like image 933
akn Avatar asked Oct 28 '25 05:10

akn


1 Answers

As I suggested in the comments, you need to use the PSource.PSpecified constructor.

The choice of words and especially the variable P which does not exists in the PKCS#1 specifications anywhere leads the user into a quagmire of terms in the world of ASN.1 specifications, not the place where you want to be.

I've concluded that the Java designers / devs meant id-pSpecified where P is then the EncodedParameters, which is the old world for the term "label". That in turn would mean that the constructor PSource.PSpecified can be used to indicate the (character-encoded) label. So although the term "label" could possibly indicate a string, it doesn't in the world of cryptography; you will have to perform some kind of character conversion yourself, and this character encoding should be documented if you'd were to use a textual label.


// 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));
}

By the way, above of course uses import static StandardCharsets.US_ASCII; in case your IDE doesn't know how to find that.


Note that PKCS#1 only seems to allow empty (octet) strings as label, other use it outside the scope of 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.

So using any L other than the empty string places you outside standard use of OAEP and you'll have to explicitly define such usages yourself. If you have some kind of identifier you might be better encoding it into the plaintext message, as libraries may not provide support for labels other than the empty string.


Finally, some nitty-gritty on how the terms are used and the actual ASN.1 definions:

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))

This largely explains how the Java specifications came to be. They actually make a lot of sense if you regard them after reading the specification - except for referring to P as separate variable within the specification of course.

like image 141
Maarten Bodewes Avatar answered Oct 29 '25 20:10

Maarten Bodewes



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!