I have been asked to generate the RSA key using given modulus
and exponent
values.
But I have idea only about generating the keys without specifying the modulus and exponent. Whatever the value I am given is seems to be big integer values. I searched about this in web and worked out some thing, But it could not went through success.
So if anybody has done this before, can they give me some hints please?
This is sample program we have tried with given values.
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.RSAKeyGenParameterSpec;
import java.security.spec.RSAPrivateKeySpec;
import java.security.spec.RSAPublicKeySpec;
public class Sample {
public static void main( String args[] ) {
BigInteger modulus = new BigInteger("350871044328208704010580786055405681");
BigInteger exponent = new BigInteger("545161406957801571");
try {
RSAPublicKeySpec spec = new RSAPublicKeySpec(modulus, exponent);
RSAPrivateKeySpec privateSpec = new RSAPrivateKeySpec(modulus, exponent);
KeyFactory factory = KeyFactory.getInstance("RSA");
PublicKey pub = factory.generatePublic(spec);
PrivateKey priv = factory.generatePrivate(privateSpec);
System.out.println("Public Key : "+ byteArrayToHexString( pub.getEncoded() ));
System.out.println("Private Key : "+ byteArrayToHexString( priv.getEncoded() ));
}
catch( Exception e ) {
System.out.println(e.toString());
}
}
public static String byteArrayToHexString(byte[] bytes)
{
StringBuffer buffer = new StringBuffer();
for(int i=0; i<bytes.length; i++)
{
if(((int)bytes[i] & 0xff) < 0x10)
buffer.append("0");
buffer.append(Long.toString((int) bytes[i] & 0xff, 16));
}
return buffer.toString();
}
}
ERROR:
java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: RSA keys must be at least 512 bits long
To generate public key from the exponent and modulus, they need to be transformed to BigInteger, and then KeyFactory from Java security can be used.
Modulus (n) is the product of two prime numbers used to generate the key pair. Public exponent (d) is the exponent used on signed / encoded data to decode the original value.
At the center of the RSA cryptosystem is the RSA modulus N. It is a positive integer which equals the product of two distinct prime numbers p and q: RSA modulus: N = pq.
The pair {n, e} is the public key. It is designed to be shared with everyone. The number e is called "public key exponent". It is usually 65537 (0x010001).
I give you some information about RSA. First of all in RSA keys the modulus = p·q
where p
and q
are distinct prime numbers, the modulus length it's the key length
. So when you are receiving the exception:
java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: RSA keys must be at least 512 bits long
This means that your modulus at least must be 512 bits long.
Besides in your code there is also another error, you're using the same exponent for public and private key, but this exponents must be different numbers.
In resume you have to calculate the modulus, public exponent and private exponent with java.math.BigInteger
following the RSA key generation algorithm to generate a correct keys. I give you an example from your code:
import java.math.BigInteger;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.spec.RSAPrivateKeySpec;
import java.security.spec.RSAPublicKeySpec;
public class Sample {
public static void main( String args[] ) {
int keySize = 512;
SecureRandom random = new SecureRandom();
// Choose two distinct prime numbers p and q.
BigInteger p = BigInteger.probablePrime(keySize/2,random);
BigInteger q = BigInteger.probablePrime(keySize/2,random);
// Compute n = pq (modulus)
BigInteger modulus = p.multiply(q);
// Compute φ(n) = φ(p)φ(q) = (p − 1)(q − 1) = n - (p + q -1), where φ is Euler's totient function.
// and choose an integer e such that 1 < e < φ(n) and gcd(e, φ(n)) = 1; i.e., e and φ(n) are coprime.
BigInteger m = (p.subtract(BigInteger.ONE)).multiply(q.subtract(BigInteger.ONE));
BigInteger publicExponent = getCoprime(m,random);
// Determine d as d ≡ e−1 (mod φ(n)); i.e., d is the multiplicative inverse of e (modulo φ(n)).
BigInteger privateExponent = publicExponent.modInverse(m);
try {
RSAPublicKeySpec spec = new RSAPublicKeySpec(modulus, publicExponent);
RSAPrivateKeySpec privateSpec = new RSAPrivateKeySpec(modulus, privateExponent);
KeyFactory factory = KeyFactory.getInstance("RSA");
PublicKey pub = factory.generatePublic(spec);
PrivateKey priv = factory.generatePrivate(privateSpec);
System.out.println("Public Key : "+ byteArrayToHexString( pub.getEncoded() ));
System.out.println("Private Key : "+ byteArrayToHexString( priv.getEncoded() ));
}
catch( Exception e ) {
System.out.println(e.toString());
}
}
public static BigInteger getCoprime(BigInteger m, SecureRandom random) {
int length = m.bitLength()-1;
BigInteger e = BigInteger.probablePrime(length,random);
while (! (m.gcd(e)).equals(BigInteger.ONE) ) {
e = BigInteger.probablePrime(length,random);
}
return e;
}
public static String byteArrayToHexString(byte[] bytes)
{
StringBuffer buffer = new StringBuffer();
for(int i=0; i<bytes.length; i++)
{
if(((int)bytes[i] & 0xff) < 0x10)
buffer.append("0");
buffer.append(Long.toString((int) bytes[i] & 0xff, 16));
}
return buffer.toString();
}
}
Hope this help,
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With