org.soulwing.credo.service.crypto.bc.BcPKCS8PrivateKeyWrapper.java Source code

Java tutorial

Introduction

Here is the source code for org.soulwing.credo.service.crypto.bc.BcPKCS8PrivateKeyWrapper.java

Source

/*
 * File created on Mar 2, 2014 
 *
 * Copyright (c) 2014 Virginia Polytechnic Institute and State University
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */
package org.soulwing.credo.service.crypto.bc;

import java.io.IOException;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;

import org.apache.commons.lang.Validate;
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import org.bouncycastle.openssl.jcajce.JceOpenSSLPKCS8DecryptorProviderBuilder;
import org.bouncycastle.operator.InputDecryptorProvider;
import org.bouncycastle.operator.OperatorCreationException;
import org.bouncycastle.pkcs.PKCS8EncryptedPrivateKeyInfo;
import org.bouncycastle.pkcs.PKCSException;
import org.soulwing.credo.service.crypto.IncorrectPassphraseException;
import org.soulwing.credo.service.crypto.PrivateKeyWrapper;
import org.soulwing.credo.service.pem.PemObjectBuilderFactory;

/**
 * A {@link PrivateKeyWrapper} that wraps a Bouncy Castle PKCS8 
 * EncryptedPrivateKeyInfo object.
 *
 * @author Carl Harris
 */
public class BcPKCS8PrivateKeyWrapper implements PrivateKeyWrapper {

    private final PKCS8EncryptedPrivateKeyInfo delegate;
    private final KeyFactory keyFactory;
    private final PemObjectBuilderFactory objectBuilderFactory;

    private char[] passphrase;

    /**
     * Constructs a new instance.
     * @param delegate PKCS8 encryptedPrivateKeyInfo
     * @param keyFactory RSA key factory
     * @param objectBuilderFactory PEM object builder factory
     */
    public BcPKCS8PrivateKeyWrapper(PKCS8EncryptedPrivateKeyInfo delegate, KeyFactory keyFactory,
            PemObjectBuilderFactory objectBuilderFactory) {
        this.delegate = delegate;
        this.keyFactory = keyFactory;
        this.objectBuilderFactory = objectBuilderFactory;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean isProtected() {
        return true;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public char[] getProtectionParameter() {
        return passphrase;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void setProtectionParameter(Object parameter) {
        Validate.isTrue(parameter instanceof char[], "requires a passphrase");
        this.passphrase = (char[]) parameter;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String getContent() {
        try {
            return objectBuilderFactory.newBuilder().setType("ENCRYPTED PRIVATE KEY").append(delegate.getEncoded())
                    .build().getEncoded();
        } catch (IOException ex) {
            throw new RuntimeException(ex);
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public PrivateKey derive() {
        Validate.notNull(passphrase, "passphrase is required");
        InputDecryptorProvider decryptor = createPrivateKeyDecryptor();
        try {
            PrivateKeyInfo keyInfo = delegate.decryptPrivateKeyInfo(decryptor);
            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyInfo.getEncoded());
            return keyFactory.generatePrivate(keySpec);
        } catch (PKCSException ex) {
            throw new IncorrectPassphraseException();
        } catch (InvalidKeySpecException ex) {
            throw new RuntimeException(ex);
        } catch (IOException ex) {
            throw new RuntimeException(ex);
        }
    }

    private InputDecryptorProvider createPrivateKeyDecryptor() {
        try {
            InputDecryptorProvider decryptor = new JceOpenSSLPKCS8DecryptorProviderBuilder().build(passphrase);
            return decryptor;
        } catch (OperatorCreationException ex) {
            throw new RuntimeException(ex);
        }
    }

}