Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using RSA encryption in Java without BouncyCastle

In my program, I'm trying to encrypt some plaintext with RSA using the following code:

static String RSAEncrypt(String pubkey, String plain){
    return encrypt(pubkey,plain,"RSA");
}
static String encrypt(String stringKey, String plain, String algo){
    String enc="failed";
    try{
    byte[] byteKey  = new BASE64Decoder().decodeBuffer(stringKey);
    Key key = new SecretKeySpec(byteKey,algo);

    byte[] data = plain.getBytes();
    Cipher c = Cipher.getInstance(algo);
    c.init(Cipher.ENCRYPT_MODE, key);
    byte[] encVal = c.doFinal(data);
    enc = new BASE64Encoder().encode(encVal);
    }catch(Exception e){e.printStackTrace();}

    return enc;
}

However, when it runs, it shows the following error:

java.security.InvalidKeyException: No installed provider supports this key: javax.crypto.spec.SecretKeySpec
at javax.crypto.Cipher.chooseProvider(Cipher.java:877)
at javax.crypto.Cipher.init(Cipher.java:1212)
at javax.crypto.Cipher.init(Cipher.java:1152)
at Crypto.encrypt(Crypto.java:37)
at Crypto.RSAEncrypt(Crypto.java:62)

I have tried changing it to RSA/None/PKCS1Padding and RSA/ECB/PKCS1Padding to no avail.. I know that installing BouncyCastle may help but I'd like to avoid it (I'd like to avoid more dependencies and I've been having some issues installing it anyway). Thanks in advance for any ideas.

like image 347
user1394672 Avatar asked Jun 18 '26 14:06

user1394672


1 Answers

As was said in the comments, SecretKeySpec is for symmetric algorithms only. You mentioned that you got your byte[] containing the key by calling getEncoded.

There are two possibilities and two resulting formats:

Encoding of an RSA PrivateKey

Calling PrivateKey#getEncoded on an instance of an RSA private key will result in a PKCS#8 encoding for private keys, and it can be restored with the help of PKCS8EncodedKeySpec.

Encoding of an RSA PublicKey

PublicKey#getEncoded on an RSA public key results in the generic X.509 public key encoding, and can be restored with X509EncodedKeySpec.

Example Usage

byte[] data = "test".getBytes("UTF8");
KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
kpg.initialize(512);
KeyPair keyPair = kpg.genKeyPair();
        
byte[] pk = keyPair.getPublic().getEncoded();
X509EncodedKeySpec spec = new X509EncodedKeySpec(pk);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PublicKey pubKey = keyFactory.generatePublic(spec);
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.ENCRYPT_MODE, pubKey);
byte[] encrypted = cipher.doFinal(data);
        
byte[] priv = keyPair.getPrivate().getEncoded();
PKCS8EncodedKeySpec spec2 = new PKCS8EncodedKeySpec(priv);
PrivateKey privKey = keyFactory.generatePrivate(spec2);
cipher.init(Cipher.DECRYPT_MODE, privKey);
byte[] plain = cipher.doFinal(encrypted);
        
System.out.println(new String(plain, "UTF8")); //=> "test"
like image 88
emboss Avatar answered Jun 21 '26 04:06

emboss