Reputation: 19
I am trying to create a cipher in order to encode an AES key that I have created. I had read in a public key from a file that I stored the public key in and converted it from bytes to a public key object. When I try to initilize the cipher using this public key, I get the error "No installed provider supports this key: sun.security.rsa.RSAPublicKeyImpl" at cipherAES.init(Cipher.ENCRYPT_MODE, DecodedPublicKey);
So when I create a RSA 2048 key generator object to get the provider, which is the specifications I used in order to create the previous key in another program, I get the error "No such algorithm: AES/GCM/NoPadding" at Cipher cipherAES = Cipher.getInstance("AES/GCM/NoPadding", kpgenProv.getName());
I need to use the transformation AES/GCM/NoPadding, and the provider that is being given from the .getProvider seems to be right, which is SunRsaSign. Does anyone have any insight into this problem? It recognizes the transformation fine when there is no provider, but rejects it when there is a provider.
String pubAlgo = publicKeyScanner.nextLine(); // not used
String PublicKey = publicKeyScanner.nextLine(); // this will stop when it hits a newline and the encoded key may have the newline char value causing the private key to be piecemeal
byte[] decodedPublicKey = Base64.getDecoder().decode(PublicKey);
KeyFactory kf = KeyFactory.getInstance("RSA"); // or "EC" or whatever
PublicKey DecodedPublicKey = kf.generatePublic(new X509EncodedKeySpec(decodedPublicKey));
publicKeyScanner.close();
System.out.println(DecodedPublicKey.toString());
KeyGenerator keyGen = KeyGenerator.getInstance("AES");
keyGen.init(128); // for example
SecretKey AESKey = keyGen.generateKey();
KeyPairGenerator kpgen = KeyPairGenerator.getInstance("RSA");
kpgen.initialize(2048);
Provider kpgenProv = kpgen.getProvider();
System.out.println(kpgenProv.getName());
Cipher cipherAES = Cipher.getInstance("AES/GCM/NoPadding", kpgenProv.getName());
cipherAES.init(Cipher.ENCRYPT_MODE, DecodedPublicKey);
byte[] AESKEYBYTES = AESKey.getEncoded();```
Upvotes: 0
Views: 2741
Reputation: 6414
Java JDK's usually are delivered with some security providers that are responsible for cryptographic operations. Due to historical reasons they didn't got combined/bundled but exist beneath each other. If you choose an algorithm by instantiating Java will find out which provider is "responsible" for this algorithm and takes him.
On the other hand - if you like to use a specific provider you can name the provider during instantiation (that's what you are doing with the second parameter "kpgenProv.getName":
Cipher.getInstance("AES/GCM/NoPadding", kpgenProv.getName())
As you see in my simple program there are two different provider for "RSA" and "AES/GCM/NoPadding" but when forcing a specific provider you receive a "no-installed-provider-supports..." exception.
So usually you leave out the provider name and let Java choose for the "best" provider for this algorithm.
output on my system (OpenJDK11):
Get security provider
provider for RSA encryption: SunRsaSign version 11
provider for AES/GCM/NoPadding: SunJCE version 11
code:
import javax.crypto.Cipher;
import javax.crypto.NoSuchPaddingException;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
public class Main {
public static void main(String[] args) throws NoSuchAlgorithmException, NoSuchPaddingException {
System.out.println("Get security provider");
KeyFactory kf = KeyFactory.getInstance("RSA");
System.out.println("provider for RSA encryption: " + kf.getProvider());
Cipher cipherAES = Cipher.getInstance("AES/GCM/NoPadding");
System.out.println("provider for AES/GCM/NoPadding: " + cipherAES.getProvider());
}
}
Upvotes: 2