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"); } }
/** * Returns the key size of the given key object. * * @param key the key object. * @return the key size of the given key object. * @exception InvalidKeyException if <code>key</code> is invalid. */ protected int engineGetKeySize(Key key) throws InvalidKeyException { byte[] encoded = key.getEncoded(); if (encoded.length != 8) { throw new InvalidKeyException("Invalid key length: " + encoded.length + " bytes"); } return 56; }
/** * Assigns the given key to the given alias, protecting it with the given password. * * <p>If the given key is of type <code>java.security.PrivateKey</code>, it must be accompanied by * a certificate chain certifying the corresponding public key. * * <p>If the given alias already exists, the keystore information associated with it is overridden * by the given key (and possibly certificate chain). * * @param alias the alias name * @param key the key to be associated with the alias * @param password the password to protect the key * @param chain the certificate chain for the corresponding public key (only required if the given * key is of type <code>java.security.PrivateKey</code>). * @exception KeyStoreException if the given key cannot be protected, or this operation fails for * some other reason */ public void engineSetKeyEntry(String alias, Key key, char[] password, Certificate[] chain) throws KeyStoreException { permissionCheck(); synchronized (entries) { try { KeyEntry entry = new KeyEntry(); entry.date = new Date(); if (key instanceof PrivateKey) { if ((key.getFormat().equals("PKCS#8")) || (key.getFormat().equals("PKCS8"))) { entry.protectedPrivKey = encryptPrivateKey(key.getEncoded(), password); entry.password = password.clone(); } else { throw new KeyStoreException("Private key is not encoded as PKCS#8"); } } else { throw new KeyStoreException("Key is not a PrivateKey"); } // clone the chain if (chain != null) { if ((chain.length > 1) && !validateChain(chain)) { throw new KeyStoreException("Certificate chain does not validate"); } entry.chain = chain.clone(); entry.chainRefs = new long[entry.chain.length]; } String lowerAlias = alias.toLowerCase(); if (entries.get(lowerAlias) != null) { deletedEntries.put(lowerAlias, entries.get(lowerAlias)); } entries.put(lowerAlias, entry); addedEntries.put(lowerAlias, entry); } catch (Exception nsae) { KeyStoreException ke = new KeyStoreException("Key protection algorithm not found: " + nsae); ke.initCause(nsae); throw ke; } } }
void implInit( int opmode, Key key, AlgorithmParameterSpec params, SecureRandom random, CipherSpi cipherImpl) throws InvalidKeyException, InvalidAlgorithmParameterException { char[] passwdChars = null; salt = null; iCount = 0; if (key instanceof javax.crypto.interfaces.PBEKey) { javax.crypto.interfaces.PBEKey pbeKey = (javax.crypto.interfaces.PBEKey) key; passwdChars = pbeKey.getPassword(); salt = pbeKey.getSalt(); // maybe null if unspecified iCount = pbeKey.getIterationCount(); // maybe 0 if unspecified } else if (key instanceof SecretKey) { byte[] passwdBytes = key.getEncoded(); if ((passwdBytes == null) || !(key.getAlgorithm().regionMatches(true, 0, "PBE", 0, 3))) { throw new InvalidKeyException("Missing password"); } passwdChars = new char[passwdBytes.length]; for (int i = 0; i < passwdChars.length; i++) { passwdChars[i] = (char) (passwdBytes[i] & 0x7f); } } else { throw new InvalidKeyException("SecretKey of PBE type required"); } if (((opmode == Cipher.DECRYPT_MODE) || (opmode == Cipher.UNWRAP_MODE)) && ((params == null) && ((salt == null) || (iCount == 0)))) { throw new InvalidAlgorithmParameterException("Parameters missing"); } if (params == null) { // generate default for salt and iteration count if necessary if (salt == null) { salt = new byte[DEFAULT_SALT_LENGTH]; if (random != null) { random.nextBytes(salt); } else { SunJCE.getRandom().nextBytes(salt); } } if (iCount == 0) iCount = DEFAULT_COUNT; } else if (!(params instanceof PBEParameterSpec)) { throw new InvalidAlgorithmParameterException("PBEParameterSpec type required"); } else { PBEParameterSpec pbeParams = (PBEParameterSpec) params; // make sure the parameter values are consistent if (salt != null) { if (!Arrays.equals(salt, pbeParams.getSalt())) { throw new InvalidAlgorithmParameterException( "Inconsistent value of salt between key and params"); } } else { salt = pbeParams.getSalt(); } if (iCount != 0) { if (iCount != pbeParams.getIterationCount()) { throw new InvalidAlgorithmParameterException( "Different iteration count between key and params"); } } else { iCount = pbeParams.getIterationCount(); } } // salt is recommended to be ideally as long as the output // of the hash function. However, it may be too strict to // force this; so instead, we'll just require the minimum // salt length to be 8-byte which is what PKCS#5 recommends // and openssl does. if (salt.length < 8) { throw new InvalidAlgorithmParameterException("Salt must be at least 8 bytes long"); } if (iCount <= 0) { throw new InvalidAlgorithmParameterException("IterationCount must be a positive number"); } byte[] derivedKey = derive(passwdChars, salt, iCount, keySize, CIPHER_KEY); SecretKey cipherKey = new SecretKeySpec(derivedKey, algo); if (cipherImpl != null && cipherImpl instanceof ARCFOURCipher) { ((ARCFOURCipher) cipherImpl).engineInit(opmode, cipherKey, random); } else { byte[] derivedIv = derive(passwdChars, salt, iCount, 8, CIPHER_IV); IvParameterSpec ivSpec = new IvParameterSpec(derivedIv, 0, 8); // initialize the underlying cipher cipher.init(opmode, cipherKey, ivSpec, random); } }