001package com.box.sdk;
002
003import java.io.IOException;
004import java.io.StringReader;
005import java.security.PrivateKey;
006import java.security.Security;
007import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
008import org.bouncycastle.jce.provider.BouncyCastleProvider;
009import org.bouncycastle.openssl.PEMDecryptorProvider;
010import org.bouncycastle.openssl.PEMEncryptedKeyPair;
011import org.bouncycastle.openssl.PEMKeyPair;
012import org.bouncycastle.openssl.PEMParser;
013import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
014import org.bouncycastle.openssl.jcajce.JceOpenSSLPKCS8DecryptorProviderBuilder;
015import org.bouncycastle.openssl.jcajce.JcePEMDecryptorProviderBuilder;
016import org.bouncycastle.operator.InputDecryptorProvider;
017import org.bouncycastle.operator.OperatorCreationException;
018import org.bouncycastle.pkcs.PKCS8EncryptedPrivateKeyInfo;
019import org.bouncycastle.pkcs.PKCSException;
020
021/**
022 * The default implementation of `IPrivateKeyDecryptor`, which uses Bouncy Castle library to decrypt
023 * the private key.
024 */
025public class BCPrivateKeyDecryptor implements IPrivateKeyDecryptor {
026
027  /**
028   * Decrypts private key with provided passphrase using Bouncy Castle library
029   *
030   * @param encryptedPrivateKey Encoded private key string.
031   * @param passphrase Private key passphrase.
032   * @return java.security.PrivateKey instance representing decrypted private key.
033   */
034  @Override
035  public PrivateKey decryptPrivateKey(String encryptedPrivateKey, String passphrase) {
036    Security.addProvider(new BouncyCastleProvider());
037    PrivateKey decryptedPrivateKey;
038    try {
039      PEMParser keyReader = new PEMParser(new StringReader(encryptedPrivateKey));
040      Object keyPair = keyReader.readObject();
041      keyReader.close();
042
043      if (keyPair instanceof PrivateKeyInfo) {
044        PrivateKeyInfo keyInfo = (PrivateKeyInfo) keyPair;
045        decryptedPrivateKey = (new JcaPEMKeyConverter()).getPrivateKey(keyInfo);
046      } else if (keyPair instanceof PEMEncryptedKeyPair) {
047        JcePEMDecryptorProviderBuilder builder = new JcePEMDecryptorProviderBuilder();
048        PEMDecryptorProvider decryptionProvider = builder.build(passphrase.toCharArray());
049        keyPair = ((PEMEncryptedKeyPair) keyPair).decryptKeyPair(decryptionProvider);
050        PrivateKeyInfo keyInfo = ((PEMKeyPair) keyPair).getPrivateKeyInfo();
051        decryptedPrivateKey = (new JcaPEMKeyConverter()).getPrivateKey(keyInfo);
052      } else if (keyPair instanceof PKCS8EncryptedPrivateKeyInfo) {
053        InputDecryptorProvider pkcs8Prov =
054            new JceOpenSSLPKCS8DecryptorProviderBuilder()
055                .setProvider("BC")
056                .build(passphrase.toCharArray());
057        PrivateKeyInfo keyInfo =
058            ((PKCS8EncryptedPrivateKeyInfo) keyPair).decryptPrivateKeyInfo(pkcs8Prov);
059        decryptedPrivateKey = (new JcaPEMKeyConverter()).getPrivateKey(keyInfo);
060      } else {
061        PrivateKeyInfo keyInfo = ((PEMKeyPair) keyPair).getPrivateKeyInfo();
062        decryptedPrivateKey = (new JcaPEMKeyConverter()).getPrivateKey(keyInfo);
063      }
064    } catch (IOException e) {
065      throw new BoxAPIException("Error parsing private key for Box Developer Edition.", e);
066    } catch (OperatorCreationException e) {
067      throw new BoxAPIException("Error parsing PKCS#8 private key for Box Developer Edition.", e);
068    } catch (PKCSException e) {
069      throw new BoxAPIException("Error parsing PKCS private key for Box Developer Edition.", e);
070    }
071    return decryptedPrivateKey;
072  }
073}