org.xipki.security.p11.P11ContentSignerBuilder.java Source code

Java tutorial

Introduction

Here is the source code for org.xipki.security.p11.P11ContentSignerBuilder.java

Source

/*
 *
 * This file is part of the XiPKI project.
 * Copyright (c) 2014 - 2015 Lijun Liao
 * Author: Lijun Liao
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License version 3
 * as published by the Free Software Foundation with the addition of the
 * following permission added to Section 15 as permitted in Section 7(a):
 * FOR ANY PART OF THE COVERED WORK IN WHICH THE COPYRIGHT IS OWNED BY
 * THE AUTHOR LIJUN LIAO. LIJUN LIAO DISCLAIMS THE WARRANTY OF NON INFRINGEMENT
 * OF THIRD PARTY RIGHTS.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * The interactive user interfaces in modified source and object code versions
 * of this program must display Appropriate Legal Notices, as required under
 * Section 5 of the GNU Affero General Public License.
 *
 * You can be released from the requirements of the license by purchasing
 * a commercial license. Buying such a license is mandatory as soon as you
 * develop commercial activities involving the XiPKI software without
 * disclosing the source code of your own applications.
 *
 * For more information, please contact Lijun Liao at this
 * address: lijun.liao@gmail.com
 */

package org.xipki.security.p11;

import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.security.interfaces.DSAPublicKey;
import java.security.interfaces.ECPublicKey;
import java.security.interfaces.RSAPublicKey;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.crypto.NoSuchPaddingException;

import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.operator.ContentSigner;
import org.bouncycastle.operator.OperatorCreationException;
import org.xipki.common.ParamChecker;
import org.xipki.common.util.AlgorithmUtil;
import org.xipki.common.util.X509Util;
import org.xipki.security.DefaultConcurrentContentSigner;
import org.xipki.security.api.ConcurrentContentSigner;
import org.xipki.security.api.SignerException;
import org.xipki.security.api.p11.P11CryptService;
import org.xipki.security.api.p11.P11KeyIdentifier;
import org.xipki.security.api.p11.P11SlotIdentifier;
import org.xipki.security.provider.P11PrivateKey;

/**
 * @author Lijun Liao
 */

public class P11ContentSignerBuilder {
    private final X509Certificate[] certificateChain;

    private final P11CryptService cryptService;
    private final P11SlotIdentifier slot;
    private final P11KeyIdentifier keyId;

    public P11ContentSignerBuilder(final P11CryptService cryptService, final P11SlotIdentifier slot,
            final P11KeyIdentifier keyId, final X509Certificate[] certificateChain) throws SignerException {
        ParamChecker.assertNotNull("cryptService", cryptService);
        ParamChecker.assertNotNull("slot", slot);
        ParamChecker.assertNotNull("keyId", keyId);

        X509Certificate signerCertInP11 = cryptService.getCertificate(slot, keyId);
        boolean keyExists = (signerCertInP11 != null);
        if (keyExists == false) {
            keyExists = (cryptService.getPublicKey(slot, keyId) != null);
        }

        if (keyExists == false) {
            throw new SignerException("key with " + keyId + " does not exist");
        }

        this.cryptService = cryptService;
        this.keyId = keyId;
        this.slot = slot;

        Set<Certificate> caCerts = new HashSet<>();

        X509Certificate cert;
        int n = certificateChain == null ? 0 : certificateChain.length;
        if (n > 0) {
            cert = certificateChain[0];
            if (n > 1) {
                for (int i = 1; i < n; i++) {
                    caCerts.add(certificateChain[i]);
                }
            }
        } else {
            cert = signerCertInP11;
        }

        Certificate[] certsInKeystore = cryptService.getCertificates(slot, keyId);
        if (certsInKeystore.length > 1) {
            for (int i = 1; i < certsInKeystore.length; i++) {
                caCerts.add(certsInKeystore[i]);
            }
        }

        this.certificateChain = X509Util.buildCertPath(cert, caCerts);
    }

    public ConcurrentContentSigner createSigner(final AlgorithmIdentifier signatureAlgId, final int parallelism)
            throws OperatorCreationException, NoSuchPaddingException {
        if (parallelism < 1) {
            throw new IllegalArgumentException("non-positive parallelism is not allowed: " + parallelism);
        }

        List<ContentSigner> signers = new ArrayList<>(parallelism);

        PublicKey publicKey = certificateChain[0].getPublicKey();
        try {
            for (int i = 0; i < parallelism; i++) {
                ContentSigner signer;
                if (publicKey instanceof RSAPublicKey) {
                    if (PKCSObjectIdentifiers.id_RSASSA_PSS.equals(signatureAlgId.getAlgorithm())) {
                        signer = new P11RSAPSSContentSigner(cryptService, slot, keyId, signatureAlgId);
                    } else {
                        signer = new P11RSAContentSigner(cryptService, slot, keyId, signatureAlgId);
                    }
                } else if (publicKey instanceof ECPublicKey) {
                    if (AlgorithmUtil.isDSAPlainSigAlg(signatureAlgId)) {
                        signer = new P11ECDSAPlainContentSigner(cryptService, slot, keyId, signatureAlgId);
                    } else {
                        signer = new P11ECDSAX962ContentSigner(cryptService, slot, keyId, signatureAlgId);
                    }
                } else if (publicKey instanceof DSAPublicKey) {
                    if (AlgorithmUtil.isDSAPlainSigAlg(signatureAlgId)) {
                        signer = new P11DSAPlainContentSigner(cryptService, slot, keyId, signatureAlgId);
                    } else {
                        signer = new P11DSAX962ContentSigner(cryptService, slot, keyId, signatureAlgId);
                    }
                } else {
                    throw new OperatorCreationException("unsupported key " + publicKey.getClass().getName());
                }
                signers.add(signer);
            }
        } catch (NoSuchAlgorithmException e) {
            throw new OperatorCreationException("no such algorithm", e);
        }

        PrivateKey privateKey;
        try {
            privateKey = new P11PrivateKey(cryptService, slot, keyId);
        } catch (InvalidKeyException e) {
            throw new OperatorCreationException("could not construct P11PrivateKey: " + e.getMessage(), e);
        }

        DefaultConcurrentContentSigner concurrentSigner = new DefaultConcurrentContentSigner(signers, privateKey);
        concurrentSigner.setCertificateChain(certificateChain);

        return concurrentSigner;
    }
}