Ejemplo n.º 1
0
  /*
   * Encrypt private key using Password-based encryption (PBE)
   * as defined in PKCS#5.
   *
   * NOTE: Currently pbeWithSHAAnd3-KeyTripleDES-CBC algorithmID is
   *       used to derive the key and IV.
   *
   * @return encrypted private key encoded as EncryptedPrivateKeyInfo
   */
  private byte[] encryptPrivateKey(byte[] data, char[] password)
      throws IOException, NoSuchAlgorithmException, UnrecoverableKeyException {
    byte[] key = null;

    try {
      // create AlgorithmParameters
      AlgorithmParameters algParams = getAlgorithmParameters("PBEWithSHA1AndDESede");

      // Use JCE
      SecretKey skey = getPBEKey(password);
      Cipher cipher = Cipher.getInstance("PBEWithSHA1AndDESede");
      cipher.init(Cipher.ENCRYPT_MODE, skey, algParams);
      byte[] encryptedKey = cipher.doFinal(data);

      // wrap encrypted private key in EncryptedPrivateKeyInfo
      // as defined in PKCS#8
      AlgorithmId algid = new AlgorithmId(pbeWithSHAAnd3KeyTripleDESCBC_OID, algParams);
      EncryptedPrivateKeyInfo encrInfo = new EncryptedPrivateKeyInfo(algid, encryptedKey);
      key = encrInfo.getEncoded();
    } catch (Exception e) {
      UnrecoverableKeyException uke =
          new UnrecoverableKeyException("Encrypt Private Key failed: " + e.getMessage());
      uke.initCause(e);
      throw uke;
    }

    return key;
  }
Ejemplo n.º 2
0
  /*
   * Generate PBE key
   */
  private SecretKey getPBEKey(char[] password) throws IOException {
    SecretKey skey = null;

    try {
      PBEKeySpec keySpec = new PBEKeySpec(password);
      SecretKeyFactory skFac = SecretKeyFactory.getInstance("PBE");
      skey = skFac.generateSecret(keySpec);
    } catch (Exception e) {
      IOException ioe = new IOException("getSecretKey failed: " + e.getMessage());
      ioe.initCause(e);
      throw ioe;
    }
    return skey;
  }
Ejemplo n.º 3
0
  /*
   * Generate PBE Algorithm Parameters
   */
  private AlgorithmParameters getAlgorithmParameters(String algorithm) throws IOException {
    AlgorithmParameters algParams = null;

    // create PBE parameters from salt and iteration count
    PBEParameterSpec paramSpec = new PBEParameterSpec(getSalt(), iterationCount);
    try {
      algParams = AlgorithmParameters.getInstance(algorithm);
      algParams.init(paramSpec);
    } catch (Exception e) {
      IOException ioe = new IOException("getAlgorithmParameters failed: " + e.getMessage());
      ioe.initCause(e);
      throw ioe;
    }
    return algParams;
  }
Ejemplo n.º 4
0
 /*
  * parse Algorithm Parameters
  */
 private AlgorithmParameters parseAlgParameters(DerInputStream in) throws IOException {
   AlgorithmParameters algParams = null;
   try {
     DerValue params;
     if (in.available() == 0) {
       params = null;
     } else {
       params = in.getDerValue();
       if (params.tag == DerValue.tag_Null) {
         params = null;
       }
     }
     if (params != null) {
       algParams = AlgorithmParameters.getInstance("PBE");
       algParams.init(params.toByteArray());
     }
   } catch (Exception e) {
     IOException ioe = new IOException("parseAlgParameters failed: " + e.getMessage());
     ioe.initCause(e);
     throw ioe;
   }
   return algParams;
 }
Ejemplo n.º 5
0
  /**
   * Returns the key associated with the given alias, using the given password to recover it.
   *
   * @param alias the alias name
   * @param password the password for recovering the key. This password is used internally as the
   *     key is exported in a PKCS12 format.
   * @return the requested key, or null if the given alias does not exist or does not identify a
   *     <i>key entry</i>.
   * @exception NoSuchAlgorithmException if the algorithm for recovering the key cannot be found
   * @exception UnrecoverableKeyException if the key cannot be recovered (e.g., the given password
   *     is wrong).
   */
  public Key engineGetKey(String alias, char[] password)
      throws NoSuchAlgorithmException, UnrecoverableKeyException {
    permissionCheck();

    // An empty password is rejected by MacOS API, no private key data
    // is exported. If no password is passed (as is the case when
    // this implementation is used as browser keystore in various
    // deployment scenarios like Webstart, JFX and applets), create
    // a dummy password so MacOS API is happy.
    if (password == null || password.length == 0) {
      // Must not be a char array with only a 0, as this is an empty
      // string.
      if (random == null) {
        random = new SecureRandom();
      }
      password = Long.toString(random.nextLong()).toCharArray();
    }

    Object entry = entries.get(alias.toLowerCase());

    if (entry == null || !(entry instanceof KeyEntry)) {
      return null;
    }

    // This call gives us a PKCS12 bag, with the key inside it.
    byte[] exportedKeyInfo = _getEncodedKeyData(((KeyEntry) entry).keyRef, password);
    if (exportedKeyInfo == null) {
      return null;
    }

    PrivateKey returnValue = null;

    try {
      byte[] pkcs8KeyData = fetchPrivateKeyFromBag(exportedKeyInfo);
      byte[] encryptedKey;
      AlgorithmParameters algParams;
      ObjectIdentifier algOid;
      try {
        // get the encrypted private key
        EncryptedPrivateKeyInfo encrInfo = new EncryptedPrivateKeyInfo(pkcs8KeyData);
        encryptedKey = encrInfo.getEncryptedData();

        // parse Algorithm parameters
        DerValue val = new DerValue(encrInfo.getAlgorithm().encode());
        DerInputStream in = val.toDerInputStream();
        algOid = in.getOID();
        algParams = parseAlgParameters(in);

      } catch (IOException ioe) {
        UnrecoverableKeyException uke =
            new UnrecoverableKeyException(
                "Private key not stored as " + "PKCS#8 EncryptedPrivateKeyInfo: " + ioe);
        uke.initCause(ioe);
        throw uke;
      }

      // Use JCE to decrypt the data using the supplied password.
      SecretKey skey = getPBEKey(password);
      Cipher cipher = Cipher.getInstance(algOid.toString());
      cipher.init(Cipher.DECRYPT_MODE, skey, algParams);
      byte[] decryptedPrivateKey = cipher.doFinal(encryptedKey);
      PKCS8EncodedKeySpec kspec = new PKCS8EncodedKeySpec(decryptedPrivateKey);

      // Parse the key algorithm and then use a JCA key factory to create the private key.
      DerValue val = new DerValue(decryptedPrivateKey);
      DerInputStream in = val.toDerInputStream();

      // Ignore this -- version should be 0.
      int i = in.getInteger();

      // Get the Algorithm ID next
      DerValue[] value = in.getSequence(2);
      AlgorithmId algId = new AlgorithmId(value[0].getOID());
      String algName = algId.getName();

      // Get a key factory for this algorithm.  It's likely to be 'RSA'.
      KeyFactory kfac = KeyFactory.getInstance(algName);
      returnValue = kfac.generatePrivate(kspec);
    } catch (Exception e) {
      UnrecoverableKeyException uke =
          new UnrecoverableKeyException("Get Key failed: " + e.getMessage());
      uke.initCause(e);
      throw uke;
    }

    return returnValue;
  }