Skip to Main Content

Java Security

Announcement

For appeals, questions and feedback about Oracle Forums, please email oracle-forums-moderators_us@oracle.com. Technical questions should be asked in the appropriate category. Thank you!

RSAES-OAEP

843811Mar 1 2007
Hello,

I wrote a program using JCA APIs to do RSA OAEP encryption, and tried to verify the code with the test vector in the RSA's OAEP document. It is a pity that the actual result is not the same as the expected one. I checked the bit string representation, construction of RSAPublicKey, initialization of the RSA cipher, generation of OAEPParameterSpec. However, I could not find what might be missing. Would anyone do me a favor to tell whether parameter setting is correct for RSA OAEP? Code is attached for reference.

Thank you so much!



-- Climenti

import java.io.*;
import java.math.BigInteger;
import java.security.*;
import java.security.spec.*;
import java.security.interfaces.*;
import javax.crypto.*;
import javax.crypto.spec.*;
import javax.crypto.interfaces.*;
import com.sun.crypto.provider.SunJCE;

public class TestRSA {

private TestRSA() {}

public static void main(String argv[]) {
try {
TestRSA rsa = new TestRSA();
rsa.run();
} catch (Exception e) {
System.out.println("Error: " + e);
System.exit(1);
}
}

private void run() throws Exception {
/*
* Verifiy the byte array is big indian format
* as expected in the RSA's OAEP document
*/
String testStr = "8c6950";
byte[] testByte = hex2bytes(testStr);
BigInteger test = new BigInteger(1, testByte);
/*
* The expected result is:
* 9202000
*/
System.out.println("The BigInteger is " + test.toString(10));

/*
* RSA modulus in hex string format
*/
String modulusStr =
"bbf82f090682ce9c2338ac2b9da871f7368d07eed41043a440d6b6f07454f51fb8dfbaaf035c02ab61ea48ceeb6fcd4876ed520d60e1ec4619719d8a5b8b807fafb8e0a3dfc737723ee6b4b7d93a2584ee6a649d060953748834b2454598394ee0aab12d7b61a51f527a9a41f6c1687fe2537298ca2a8f5946f8e5fd091dbdcb";

/*
* seed, an input parament for MGF, in hex string format,
*/
String seedStr = "aafd12f659cae63489b479e5076ddec2f06cb58f";

/*
* message in hex string format
*/
String message = "d436e99569fd32a7c8a05bbc90d32c49";

/*
* The following OAEPParameterSpec is equivalent to
* OAEPParameterSpec oaepParamSpec =
* OAEPParameterSpec.DEFAULT;
*/
String mdName = "SHA-1";
String mgfName = "MGF1";
AlgorithmParameterSpec mgfSpec = MGF1ParameterSpec.SHA1;
/*
* NULL string as encoding parameters
*/
byte encoded[] = "".getBytes();
PSource pSrc = (PSource)(new PSource.PSpecified(encoded));

OAEPParameterSpec oaepParamSpec = new OAEPParameterSpec(mdName, mgfName, mgfSpec, pSrc);

byte modulus[] = hex2bytes(modulusStr);
byte seed[] = hex2bytes(seedStr);
byte cleartext[] = hex2bytes(message);
byte expo[] = {0x11}; /* RSA public exponent*/

/*
* Check whether there is a format error
*/
if (seed == null || modulus == null || cleartext == null) return;

SecureRandom secRand = new SecureRandom(seed);

BigInteger rsa1024Modulus = new BigInteger(1, modulus);
BigInteger rsa1024Expo = new BigInteger(1, expo);

/*
* Generate RSAPublicKey
*/
RSAPublicKeySpec rsaPubSpec =
new RSAPublicKeySpec(rsa1024Modulus, rsa1024Expo);
KeyFactory keyFac = KeyFactory.getInstance("RSA");
RSAPublicKey pubKey =
(RSAPublicKey)keyFac.generatePublic(rsaPubSpec);

/*
* Perform RSA-OAEP encryption
*/
Cipher rsaCipher =
Cipher.getInstance("RSA/ECB/OAEPWITHSHA1ANDMGF1PADDING");
rsaCipher.init(Cipher.ENCRYPT_MODE,
pubKey,
oaepParamSpec,
secRand);
byte[] ciphertext = rsaCipher.doFinal(cleartext);

/*
* The expected result is:
* 12 53 e0 4d c0 a5 39 7b b4 4a 7a b8 7e 9b
* f2 a0 39 a3 3d 1e 99 6f c8 2a 94 cc d3 00
* 74 c9 5d f7 63 72 20 17 06 9e 52 68 da 5d
* 1c 0b 4f 87 2c f6 53 c1 1d f8 23 14 a6 79
* 68 df ea e2 8d ef 04 bb 6d 84 b1 c3 1d 65
* 4a 19 70 e5 78 3b d6 eb 96 a0 24 c2 ca 2f
* 4a 90 fe 9f 2e f5 c9 c1 40 e5 bb 48 da 95
* 36 ad 87 00 c8 4f c9 13 0a de a7 4e 55 8d
* 51 a7 4d df 85 d8 b5 0d e9 68 38 d6 06 3e
* 09 55
*/
System.out.println(toHexString(ciphertext));
return;
}

/*
* Converts a byte to hex digit and writes to the supplied buffer
*/
private void byte2hex(byte b, StringBuffer buf) {
char[] hexChars = { '0', '1', '2', '3', '4', '5', '6', '7', '8',
'9', 'a', 'b', 'c', 'd', 'e', 'f' };
int high = ((b & 0xf0) >> 4);
int low = (b & 0x0f);
buf.append(hexChars[high]);
buf.append(hexChars[low]);
}

/*
* Converts a byte array to hex string
*/
private String toHexString(byte[] block) {
StringBuffer buf = new StringBuffer();

int len = block.length;

for (int i = 0; i < len; i++) {
byte2hex(block, buf);
if (i < len-1) {
buf.append(":");
}
}
return buf.toString();
}

/*
* Converts a hex string to a byte array
*/
private byte[] hex2bytes(String hexString) {
byte[] hexBytes = hexString.getBytes();

if (hexBytes.length%2 != 0) return null;
byte[] byteArray = new byte[hexBytes.length/2];

try {
for (int i=0; i<byteArray.length; i++)
byteArray[i] = combine(hexBytes[2*i], hexBytes[2*i+1]);
} catch (Exception e) {
System.out.println("Error: " + e);
return null;
}

return byteArray;
}

/*
* Combines two hex characters to one byte
*/
private byte combine(byte a, byte b) throws Exception {
byte x = lookup(a);
byte y = lookup(b);

if (x == -1 || y == -1) throw new Exception("Format Error");
return ((byte)(((int)x << 4) | (int)y));
}

/*
* Transforms a hex character to corresponding number
*/
private byte lookup(byte a) {
char[] hexChars = { '0', '1', '2', '3', '4', '5', '6', '7', '8',
'9', 'a', 'b', 'c', 'd', 'e', 'f' };
for (int i=0; i<hexChars.length; i++)
if (a == (byte)hexChars[i])
return ((byte)i);
return(-1);
}

/*
* Reverse a byte array
*/
private byte[] reverse(byte[] a) {
byte b[] = new byte[a.length];

for (int i=0; i<a.length; i++)
b[i] = a[a.length-i-1];
return b;
}
}
Comments
Locked Post
New comments cannot be posted to this locked post.
Post Details
Locked on Mar 29 2007
Added on Mar 1 2007
0 comments
434 views