RSA Encryption and Signature

·

3 min read

1. RSA Encryption

  • OAEP (Optimal Asymmetric Encryption Padding):

    • The default RSA encryption padding scheme, known for its high security.

    • Enhances security using randomness and hash functions.

    • Default configuration:

      • Hash function: SHA-256 (specified by OAEPWithSHA-256AndMGF1Padding).

      • Mask Generation Function (MGF): MGF1.

      • MGF hash function: Same as the main hash function (e.g., SHA-256).

      • Label: Defaults to empty.

  • Code Example:

      Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding");
      cipher.init(Cipher.ENCRYPT_MODE, publicKey);
      byte[] encryptedBytes = cipher.doFinal(plainText.getBytes());
    

2. RSA Signature

  • PSS (Probabilistic Signature Scheme):

    • The default RSA signature padding scheme, known for its high security.

    • Uses random salt, ensuring different signatures for the same data.

    • Default configuration:

      • Hash function: SHA-256 (specified by SHA256withRSA/PSS).

      • Mask Generation Function (MGF): MGF1.

      • MGF hash function: Same as the main hash function (e.g., SHA-256).

      • Salt length: Defaults to the output length of the hash function (e.g., 32 bytes for SHA-256).

  • Code Example:

      Signature signature = Signature.getInstance("SHA256withRSA/PSS");
      signature.initSign(privateKey);
      signature.update(data);
      byte[] signatureBytes = signature.sign();
    

3. PKCS#1 and PKCS#8

  • PKCS#1:

    • Specifically for RSA keys.

    • Private key format: -----BEGIN RSA PRIVATE KEY-----.

    • Public key format: -----BEGIN RSA PUBLIC KEY-----.

  • PKCS#8:

    • A generic key format supporting multiple algorithms (e.g., RSA, ECDSA).

    • Private key format: -----BEGIN PRIVATE KEY-----.

    • Public key format: -----BEGIN PUBLIC KEY-----.

  • Default Key Generation:

    • Java and Android generate PKCS#8 private keys and X.509 public keys by default.
  • Cross-Format Signature Verification:

    • Signatures created with PKCS#8 private keys can be verified using PKCS#1 public keys without conversion.

4. MGF1 (Mask Generation Function 1)

  • Purpose:

    • Generates variable-length masks for use in OAEP and PSS.
  • Default Configuration:

    • Used by default in OAEP and PSS.

    • The MGF hash function matches the main hash function (e.g., SHA-256).


5. Code Example: Cross-Format Signature Verification

1. Generate a PKCS#8 Key Pair

KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(2048);
KeyPair keyPair = keyPairGenerator.generateKeyPair();
PrivateKey privateKey = keyPair.getPrivate(); // PKCS#8 private key
PublicKey publicKey = keyPair.getPublic();   // X.509 public key

2. Sign Data with PKCS#8 Private Key (PSS Padding)

Signature signature = Signature.getInstance("SHA256withRSA/PSS");
signature.initSign(privateKey);
signature.update(data);
byte[] signatureBytes = signature.sign();

3. Convert X.509 Public Key to PKCS#1 Format

// Assume you have converted the X.509 public key to PKCS#1 format
String pkcs1PublicKeyPEM = "-----BEGIN RSA PUBLIC KEY-----\n" +
                           "MIIBCgKCAQEA...\n" +
                           "-----END RSA PUBLIC KEY-----";

// Parse the PKCS#1 public key
byte[] pkcs1PublicKeyBytes = Base64.getDecoder().decode(pkcs1PublicKeyPEM
    .replace("-----BEGIN RSA PUBLIC KEY-----", "")
    .replace("-----END RSA PUBLIC KEY-----", "")
    .replaceAll("\\s", ""));

// Use BouncyCastle to parse the PKCS#1 public key
RSAPublicKey pkcs1PublicKey = (RSAPublicKey) KeyFactory.getInstance("RSA")
    .generatePublic(new X509EncodedKeySpec(pkcs1PublicKeyBytes));

4. Verify Signature with PKCS#1 Public Key

signature.initVerify(pkcs1PublicKey); // Use PKCS#1 public key
signature.update(data);
boolean isValid = signature.verify(signatureBytes);
System.out.println("Signature is valid: " + isValid);

6. Summary

  • OAEP is the recommended padding scheme for RSA encryption, using MGF1 by default.

  • PSS is the recommended padding scheme for RSA signatures, using MGF1 by default.

  • PKCS#8 is the default key format, while PKCS#1 is an older format. They can be converted between each other.

  • Signatures created with PKCS#8 private keys can be verified using PKCS#1 public keys without conversion.