All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.bouncycastle.openpgp.PGPV3SignatureGenerator Maven / Gradle / Ivy

package org.bouncycastle.openpgp;

import java.io.ByteArrayOutputStream;
import java.math.BigInteger;
import java.security.*;
import java.util.Date;

import org.bouncycastle.bcpg.MPInteger;
import org.bouncycastle.bcpg.OnePassSignaturePacket;
import org.bouncycastle.bcpg.PublicKeyAlgorithmTags;
import org.bouncycastle.bcpg.SignaturePacket;

/**
 * Generator for old style PGP V3 Signatures.
 */
public class PGPV3SignatureGenerator
{
    private int keyAlgorithm;
    private int hashAlgorithm;
    private PGPPrivateKey privKey;
    private Signature sig;
    private MessageDigest dig;
    private int signatureType;
    
    private byte            lastb;
    
    /**
     * Create a generator for the passed in keyAlgorithm and hashAlgorithm codes.
     * 
     * @param keyAlgorithm
     * @param hashAlgorithm
     * @param provider
     * @throws NoSuchAlgorithmException
     * @throws NoSuchProviderException
     * @throws PGPException
     */
     public PGPV3SignatureGenerator(
        int  keyAlgorithm,
        int  hashAlgorithm,
        String provider)
        throws NoSuchAlgorithmException, NoSuchProviderException, PGPException
    {
        this(keyAlgorithm, hashAlgorithm, PGPUtil.getProvider(provider));
    }

    public PGPV3SignatureGenerator(
        int  keyAlgorithm,
        int  hashAlgorithm,
        Provider provider)
        throws NoSuchAlgorithmException, PGPException
    {
        this.keyAlgorithm = keyAlgorithm;
        this.hashAlgorithm = hashAlgorithm;
        
        dig = PGPUtil.getDigestInstance(PGPUtil.getDigestName(hashAlgorithm), provider);
        sig = Signature.getInstance(PGPUtil.getSignatureName(keyAlgorithm, hashAlgorithm), provider);
    }
    
    /**
     * Initialise the generator for signing.
     * 
     * @param signatureType
     * @param key
     * @throws PGPException
     */
    public void initSign(
        int           signatureType,
        PGPPrivateKey key)
        throws PGPException
    {
        initSign(signatureType, key, null);
    }

    /**
     * Initialise the generator for signing.
     * 
     * @param signatureType
     * @param key
     * @param random
     * @throws PGPException
     */
    public void initSign(
        int           signatureType,
        PGPPrivateKey key,
        SecureRandom  random)
        throws PGPException
    {
        this.privKey = key;
        this.signatureType = signatureType;
        
        try
        {
            if (random == null)
            {
                sig.initSign(key.getKey());
            }
            else
            {
                sig.initSign(key.getKey(), random);
            }
        }
        catch (InvalidKeyException e)
        {
           throw new PGPException("invalid key.", e);
        }
        
        dig.reset();
        lastb = 0;
    }
    
    public void update(
        byte b) 
        throws SignatureException
    {
        if (signatureType == PGPSignature.CANONICAL_TEXT_DOCUMENT)
        {
            if (b == '\r')
            {
                sig.update((byte)'\r');
                sig.update((byte)'\n');
                dig.update((byte)'\r');
                dig.update((byte)'\n');
            }
            else if (b == '\n')
            {
                if (lastb != '\r')
                {
                    sig.update((byte)'\r');
                    sig.update((byte)'\n');
                    dig.update((byte)'\r');
                    dig.update((byte)'\n');
                }
            }
            else
            {
                sig.update(b);
                dig.update(b);
            }
            
            lastb = b;
        }
        else
        {
            sig.update(b);
            dig.update(b);
        }
    }
    
    public void update(
        byte[] b) 
        throws SignatureException
    {
        this.update(b, 0, b.length);
    }
    
    public void update(
        byte[]  b,
        int     off,
        int     len) 
        throws SignatureException
    {
        if (signatureType == PGPSignature.CANONICAL_TEXT_DOCUMENT)
        {
            int finish = off + len;
            
            for (int i = off; i != finish; i++)
            {
                this.update(b[i]);
            }
        }
        else
        {
            sig.update(b, off, len);
            dig.update(b, off, len);
        }
    }
    
    /**
     * Return the one pass header associated with the current signature.
     * 
     * @param isNested
     * @return PGPOnePassSignature
     * @throws PGPException
     */
    public PGPOnePassSignature generateOnePassVersion(
        boolean isNested)
        throws PGPException
    {
        return new PGPOnePassSignature(new OnePassSignaturePacket(signatureType, hashAlgorithm, keyAlgorithm, privKey.getKeyID(), isNested));
    }
    
    /**
     * Return a V3 signature object containing the current signature state.
     * 
     * @return PGPSignature
     * @throws PGPException
     * @throws SignatureException
     */
    public PGPSignature generate()
            throws PGPException, SignatureException
    {
        long creationTime = new Date().getTime() / 1000;

        ByteArrayOutputStream sOut = new ByteArrayOutputStream();

        sOut.write(signatureType);
        sOut.write((byte)(creationTime >> 24));
        sOut.write((byte)(creationTime >> 16));
        sOut.write((byte)(creationTime >> 8));
        sOut.write((byte)creationTime);

        byte[] hData = sOut.toByteArray();

        sig.update(hData);
        dig.update(hData);

        MPInteger[] sigValues;
        if (keyAlgorithm == PublicKeyAlgorithmTags.RSA_SIGN
            || keyAlgorithm == PublicKeyAlgorithmTags.RSA_GENERAL)
            // an RSA signature
        {
            sigValues = new MPInteger[1];
            sigValues[0] = new MPInteger(new BigInteger(1, sig.sign()));
        }
        else
        {
            sigValues = PGPUtil.dsaSigToMpi(sig.sign());
        }

        byte[] digest = dig.digest();
        byte[] fingerPrint = new byte[2];

        fingerPrint[0] = digest[0];
        fingerPrint[1] = digest[1];

        return new PGPSignature(new SignaturePacket(3, signatureType, privKey.getKeyID(), keyAlgorithm, hashAlgorithm, creationTime * 1000, fingerPrint, sigValues));
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy