protected <T extends KeySpec> T engineGetKeySpec(Key key, Class<T> keySpec) throws InvalidKeySpecException { try { // convert key to one of our keys // this also verifies that the key is a valid RSA key and ensures // that the encoding is X.509/PKCS#8 for public/private keys key = engineTranslateKey(key); } catch (InvalidKeyException e) { throw new InvalidKeySpecException(e); } if (key instanceof RSAPublicKey) { RSAPublicKey rsaKey = (RSAPublicKey) key; if (rsaPublicKeySpecClass.isAssignableFrom(keySpec)) { return keySpec.cast(new RSAPublicKeySpec(rsaKey.getModulus(), rsaKey.getPublicExponent())); } else if (x509KeySpecClass.isAssignableFrom(keySpec)) { return keySpec.cast(new X509EncodedKeySpec(key.getEncoded())); } else { throw new InvalidKeySpecException( "KeySpec must be RSAPublicKeySpec or " + "X509EncodedKeySpec for RSA public keys"); } } else if (key instanceof RSAPrivateKey) { if (pkcs8KeySpecClass.isAssignableFrom(keySpec)) { return keySpec.cast(new PKCS8EncodedKeySpec(key.getEncoded())); } else if (rsaPrivateCrtKeySpecClass.isAssignableFrom(keySpec)) { if (key instanceof RSAPrivateCrtKey) { RSAPrivateCrtKey crtKey = (RSAPrivateCrtKey) key; return keySpec.cast( new RSAPrivateCrtKeySpec( crtKey.getModulus(), crtKey.getPublicExponent(), crtKey.getPrivateExponent(), crtKey.getPrimeP(), crtKey.getPrimeQ(), crtKey.getPrimeExponentP(), crtKey.getPrimeExponentQ(), crtKey.getCrtCoefficient())); } else { throw new InvalidKeySpecException("RSAPrivateCrtKeySpec can only be used with CRT keys"); } } else if (rsaPrivateKeySpecClass.isAssignableFrom(keySpec)) { RSAPrivateKey rsaKey = (RSAPrivateKey) key; return keySpec.cast( new RSAPrivateKeySpec(rsaKey.getModulus(), rsaKey.getPrivateExponent())); } else { throw new InvalidKeySpecException( "KeySpec must be RSAPrivate(Crt)KeySpec or " + "PKCS8EncodedKeySpec for RSA private keys"); } } else { // should not occur, caught in engineTranslateKey() throw new InvalidKeySpecException("Neither public nor private key"); } }
// internal implementation of translateKey() for private keys. See JCA doc private PrivateKey translatePrivateKey(PrivateKey key) throws InvalidKeyException { if (key instanceof RSAPrivateCrtKey) { if (key instanceof RSAPrivateCrtKeyImpl) { return key; } RSAPrivateCrtKey rsaKey = (RSAPrivateCrtKey) key; try { return new RSAPrivateCrtKeyImpl( rsaKey.getModulus(), rsaKey.getPublicExponent(), rsaKey.getPrivateExponent(), rsaKey.getPrimeP(), rsaKey.getPrimeQ(), rsaKey.getPrimeExponentP(), rsaKey.getPrimeExponentQ(), rsaKey.getCrtCoefficient()); } catch (RuntimeException e) { // catch providers that incorrectly implement RSAPrivateCrtKey throw new InvalidKeyException("Invalid key", e); } } else if (key instanceof RSAPrivateKey) { if (key instanceof RSAPrivateKeyImpl) { return key; } RSAPrivateKey rsaKey = (RSAPrivateKey) key; try { return new RSAPrivateKeyImpl(rsaKey.getModulus(), rsaKey.getPrivateExponent()); } catch (RuntimeException e) { // catch providers that incorrectly implement RSAPrivateKey throw new InvalidKeyException("Invalid key", e); } } else if ("PKCS#8".equals(key.getFormat())) { byte[] encoded = key.getEncoded(); return RSAPrivateCrtKeyImpl.newKey(encoded); } else { throw new InvalidKeyException( "Private keys must be instance " + "of RSAPrivate(Crt)Key or have PKCS#8 encoding"); } }