Package org.vafer.jdeb.signing

Source Code of org.vafer.jdeb.signing.PGPSigner

/*
* Copyright 2014 The jdeb developers.
*
* 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.vafer.jdeb.signing;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.nio.charset.Charset;
import java.security.GeneralSecurityException;
import java.util.Iterator;

import org.apache.commons.io.LineIterator;
import org.bouncycastle.bcpg.ArmoredOutputStream;
import org.bouncycastle.bcpg.BCPGOutputStream;
import org.bouncycastle.openpgp.PGPException;
import org.bouncycastle.openpgp.PGPPrivateKey;
import org.bouncycastle.openpgp.PGPSecretKey;
import org.bouncycastle.openpgp.PGPSecretKeyRing;
import org.bouncycastle.openpgp.PGPSecretKeyRingCollection;
import org.bouncycastle.openpgp.PGPSignature;
import org.bouncycastle.openpgp.PGPSignatureGenerator;
import org.bouncycastle.openpgp.PGPUtil;
import org.bouncycastle.openpgp.operator.bc.BcPBESecretKeyDecryptorBuilder;
import org.bouncycastle.openpgp.operator.bc.BcPGPContentSignerBuilder;
import org.bouncycastle.openpgp.operator.bc.BcPGPDigestCalculatorProvider;

/**
* Signing with OpenPGP.
*
* @author Torsten Curdt
* @author Emmanuel Bourg
*/
public class PGPSigner {

    private static final byte[] EOL = "\n".getBytes(Charset.forName("UTF-8"));

    private PGPSecretKey secretKey;
    private PGPPrivateKey privateKey;

    public PGPSigner(InputStream keyring, String keyId, String passphrase) throws IOException, PGPException {
        secretKey = getSecretKey(keyring, keyId);
        if(secretKey == null)
        {
            throw new PGPException(String.format("Specified key %s does not exist in key ring %s", keyId, keyring));
        }
        privateKey = secretKey.extractPrivateKey(new BcPBESecretKeyDecryptorBuilder(new BcPGPDigestCalculatorProvider()).build(passphrase.toCharArray()));
    }

    /**
     * Creates a clear sign signature over the input data. (Not detached)
     *
     * @param input      the content to be signed
     * @param output     the output destination of the signature
     */
    public void clearSign(String input, OutputStream output) throws IOException, PGPException, GeneralSecurityException {
        clearSign(new ByteArrayInputStream(input.getBytes("UTF-8")), output);
    }

    /**
     * Creates a clear sign signature over the input data. (Not detached)
     *
     * @param input      the content to be signed
     * @param output     the output destination of the signature
     */
    public void clearSign(InputStream input, OutputStream output) throws IOException, PGPException, GeneralSecurityException {
        int digest = PGPUtil.SHA1;
       
        PGPSignatureGenerator signatureGenerator = new PGPSignatureGenerator(new BcPGPContentSignerBuilder(privateKey.getPublicKeyPacket().getAlgorithm(), digest));
        signatureGenerator.init(PGPSignature.CANONICAL_TEXT_DOCUMENT, privateKey);
       
        ArmoredOutputStream armoredOutput = new ArmoredOutputStream(output);
        armoredOutput.beginClearText(digest);
       
        LineIterator iterator = new LineIterator(new InputStreamReader(input));
       
        while (iterator.hasNext()) {
            String line = iterator.nextLine();
           
            // trailing spaces must be removed for signature calculation (see http://tools.ietf.org/html/rfc4880#section-7.1)
            byte[] data = trim(line).getBytes("UTF-8");
           
            armoredOutput.write(data);
            armoredOutput.write(EOL);
           
            signatureGenerator.update(data);
            if (iterator.hasNext()) {
                signatureGenerator.update(EOL);
            }
        }

        armoredOutput.endClearText();
       
        PGPSignature signature = signatureGenerator.generate();
        signature.encode(new BCPGOutputStream(armoredOutput));
       
        armoredOutput.close();
    }
   
    /**
     * Returns the secret key.
     */
    public PGPSecretKey getSecretKey()
    {
        return secretKey;
    }

    /**
     * Returns the private key.
     */
    public PGPPrivateKey getPrivateKey()
    {
        return privateKey;
    }

    /**
     * Returns the secret key matching the specified identifier.
     *
     * @param input the input stream containing the keyring collection
     * @param keyId the 4 bytes identifier of the key
     */
    private PGPSecretKey getSecretKey(InputStream input, String keyId) throws IOException, PGPException {
        PGPSecretKeyRingCollection keyrings = new PGPSecretKeyRingCollection(PGPUtil.getDecoderStream(input));
       
        Iterator rIt = keyrings.getKeyRings();

        while (rIt.hasNext()) {
            PGPSecretKeyRing kRing = (PGPSecretKeyRing) rIt.next();
            Iterator kIt = kRing.getSecretKeys();

            while (kIt.hasNext()) {
                PGPSecretKey key = (PGPSecretKey) kIt.next();
               
                if (key.isSigningKey() && String.format("%08x", key.getKeyID() & 0xFFFFFFFFL).equals(keyId.toLowerCase())) {
                    return key;
                }
            }
        }

        return null;
    }

    /**
     * Trim the trailing spaces.
     *
     * @param line
     */
    private String trim(String line) {
        char[] chars = line.toCharArray();
        int len = chars.length;

        while (len > 0) {
            if (!Character.isWhitespace(chars[len - 1])) {
                break;
            }
            len--;
        }
       
        return line.substring(0, len);
    }
}
TOP

Related Classes of org.vafer.jdeb.signing.PGPSigner

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.