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 the private key.
023 */
024public class BCPrivateKeyDecryptor implements IPrivateKeyDecryptor {
025
026    /**
027     * Decrypts private key with provided passphrase using Bouncy Castle library
028     *
029     * @param encryptedPrivateKey Encoded private key string.
030     * @param passphrase Private key passphrase.
031     * @return java.security.PrivateKey instance representing decrypted private key.
032     */
033    @Override
034    public PrivateKey decryptPrivateKey(String encryptedPrivateKey, String passphrase) {
035        Security.addProvider(new BouncyCastleProvider());
036        PrivateKey decryptedPrivateKey;
037        try {
038            PEMParser keyReader = new PEMParser(new StringReader(encryptedPrivateKey));
039            Object keyPair = keyReader.readObject();
040            keyReader.close();
041
042            if (keyPair instanceof PrivateKeyInfo) {
043                PrivateKeyInfo keyInfo = (PrivateKeyInfo) keyPair;
044                decryptedPrivateKey = (new JcaPEMKeyConverter()).getPrivateKey(keyInfo);
045            } else if (keyPair instanceof PEMEncryptedKeyPair) {
046                JcePEMDecryptorProviderBuilder builder = new JcePEMDecryptorProviderBuilder();
047                PEMDecryptorProvider decryptionProvider = builder.build(passphrase.toCharArray());
048                keyPair = ((PEMEncryptedKeyPair) keyPair).decryptKeyPair(decryptionProvider);
049                PrivateKeyInfo keyInfo = ((PEMKeyPair) keyPair).getPrivateKeyInfo();
050                decryptedPrivateKey = (new JcaPEMKeyConverter()).getPrivateKey(keyInfo);
051            } else if (keyPair instanceof PKCS8EncryptedPrivateKeyInfo) {
052                InputDecryptorProvider pkcs8Prov = new JceOpenSSLPKCS8DecryptorProviderBuilder()
053                        .setProvider("BC")
054                        .build(passphrase.toCharArray());
055                PrivateKeyInfo keyInfo = ((PKCS8EncryptedPrivateKeyInfo) keyPair).decryptPrivateKeyInfo(pkcs8Prov);
056                decryptedPrivateKey = (new JcaPEMKeyConverter()).getPrivateKey(keyInfo);
057            } else {
058                PrivateKeyInfo keyInfo = ((PEMKeyPair) keyPair).getPrivateKeyInfo();
059                decryptedPrivateKey = (new JcaPEMKeyConverter()).getPrivateKey(keyInfo);
060            }
061        } catch (IOException e) {
062            throw new BoxAPIException("Error parsing private key for Box Developer Edition.", e);
063        } catch (OperatorCreationException e) {
064            throw new BoxAPIException("Error parsing PKCS#8 private key for Box Developer Edition.", e);
065        } catch (PKCSException e) {
066            throw new BoxAPIException("Error parsing PKCS private key for Box Developer Edition.", e);
067        }
068        return decryptedPrivateKey;
069    }
070}