com.aqnote.shared.cryptology.asymmetric.DSA.java Source code

Java tutorial

Introduction

Here is the source code for com.aqnote.shared.cryptology.asymmetric.DSA.java

Source

/*
 * Copyright 2013-2023 "Peng Li"<aqnote@qq.com>
 * Licensed under the AQNote License, Version 1.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.aqnote.com/licenses/LICENSE-1.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 com.aqnote.shared.cryptology.asymmetric;

import static com.aqnote.shared.cryptology.util.lang.ByteUtil.toHexString;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.Signature;
import java.security.SignatureException;
import java.security.spec.EncodedKeySpec;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.codec.binary.Base64;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * DSA.java????/
 * 
 * @author "Peng Li"<aqnote@qq.com> May 7, 2012 3:38:19 PM
 */
public class DSA {

    private static final Logger log = LoggerFactory.getLogger(DSA.class);

    public static final String JCE_PROVIDER = BouncyCastleProvider.PROVIDER_NAME;
    public static final String ALGORITHM = "DSA";

    private Map<String, KeyPairEntry> keyPairs = new HashMap<String, KeyPairEntry>();

    public static KeyPair genKeyPair(int bit) {
        try {
            KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(ALGORITHM, JCE_PROVIDER);
            keyPairGen.initialize(bit, new SecureRandom());
            return keyPairGen.generateKeyPair();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (NoSuchProviderException e) {
            e.printStackTrace();
        }
        return null;
    }

    public PublicKey getPublicKey(String name) {
        KeyPairEntry entry = getEntry(name, false);
        if (entry == null) {
            return null;
        }
        return entry.publicKey;
    }

    public void setPublicKey(String name, InputStream istream) throws IOException, RuntimeException {
        setPublicKey(name, getBytes(istream));
    }

    public void setPublicKey(String name, byte[] keyBytes) throws RuntimeException {
        KeyPairEntry entry = getEntry(name, true);
        if (entry.publicKey != null) {
            throw new IllegalArgumentException("duplicated public key for name: " + name);
        }
        entry.publicKey = readPublicKey(keyBytes);
    }

    public PrivateKey getPrivateKey(String name) {
        KeyPairEntry entry = getEntry(name, false);
        if (entry == null) {
            return null;
        }
        return entry.privateKey;
    }

    public void setPrivateKey(String name, InputStream istream) throws IOException, RuntimeException {
        setPrivateKey(name, getBytes(istream));
    }

    public void setPrivateKey(String name, byte[] keyBytes) throws RuntimeException {
        KeyPairEntry entry = getEntry(name, true);
        if (entry.privateKey != null) {
            throw new IllegalArgumentException("duplicated private key for name: " + name);
        }
        entry.privateKey = readPrivateKey(keyBytes);
    }

    private KeyPairEntry getEntry(String name, boolean create) {
        KeyPairEntry entry = (KeyPairEntry) keyPairs.get(name);
        if ((entry == null) && create) {
            entry = new KeyPairEntry();
            keyPairs.put(name, entry);
        }
        return entry;
    }

    private byte[] getBytes(InputStream istream) throws IOException {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        int amount;
        byte[] buffer = new byte[8192]; // 8k
        while ((amount = istream.read(buffer)) >= 0) {
            baos.write(buffer, 0, amount);
        }
        return baos.toByteArray();
    }

    /**
     * ?public key
     * 
     * @throws RuntimeException key
     */
    public static PublicKey readPublicKey(byte[] keyBytes) throws RuntimeException {
        try {
            KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
            byte[] encodedKey = Base64.decodeBase64(keyBytes);
            EncodedKeySpec keySpec = new X509EncodedKeySpec(encodedKey);
            return keyFactory.generatePublic(keySpec);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (InvalidKeySpecException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * ?private key
     * 
     * @throws RuntimeException key
     */
    public static PrivateKey readPrivateKey(byte[] keyBytes) throws RuntimeException {
        try {
            KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
            byte[] encodedKey = Base64.decodeBase64(keyBytes);
            EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(encodedKey);
            return keyFactory.generatePrivate(keySpec);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (InvalidKeySpecException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * ??
     * 
     * @param content ???
     * @param keyPairName key pair
     * @return base64???
     */
    public String sign(String content, String keyPairName) throws RuntimeException {
        return sign(getBytes(content, null), keyPairName);
    }

    /**
     * ??
     * 
     * @param content ???
     * @param keyPairName key pair
     * @param charset ?
     * @return base64???
     */
    public String sign(String content, String keyPairName, String charset) throws RuntimeException {
        return sign(getBytes(content, charset), keyPairName);
    }

    /**
     * ???
     * 
     * @param content ????
     * @param keyPairName key pair
     * @return base64???
     */
    public String sign(byte[] content, String keyPairName) throws RuntimeException {
        KeyPairEntry entry = (KeyPairEntry) keyPairs.get(keyPairName);
        if (entry == null || entry.privateKey == null) {
            return null;
        }

        try {
            Signature signature = Signature.getInstance(ALGORITHM);
            signature.initSign(entry.privateKey);
            signature.update((byte[]) content);
            byte[] signed = signature.sign();

            if (log.isDebugEnabled()) {
                log.debug("Java signature[length=" + signed.length + "]: " + toHexString(signed));
            }

            return Base64.encodeBase64String(signed);
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (SignatureException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * content??
     * 
     * @param content ?
     * @param signature ??
     * @param keyPairName key pair
     * @return ??<code>true</code>
     */
    public boolean verify(String content, String signature, String keyPairName) throws RuntimeException {
        return verify(getBytes(content, null), signature, keyPairName);
    }

    /**
     * content??
     * 
     * @param content ?
     * @param signature ??
     * @param keyPairName key pair
     * @param ?
     * @return ??<code>true</code>
     */
    public boolean verify(String content, String signature, String keyPairName, String charset)
            throws RuntimeException {
        return verify(getBytes(content, charset), signature, keyPairName);
    }

    /**
     * content??
     * 
     * @param content ?
     * @param signature ??
     * @param keyPairName key pair
     * @return ??<code>true</code>
     */
    public boolean verify(byte[] content, String signature, String keyPairName) throws RuntimeException {
        KeyPairEntry entry = (KeyPairEntry) keyPairs.get(keyPairName);
        if (entry == null || entry.publicKey == null) {
            return false;
        }

        try {
            byte[] signed = Base64.decodeBase64(signature);

            if (log.isDebugEnabled()) {
                log.debug("Java signature[length=" + signed.length + "]: " + toHexString(signed));
            }

            Signature sign = Signature.getInstance(ALGORITHM);
            sign.initVerify(entry.publicKey);
            sign.update((byte[]) content);

            return sign.verify(signed);
        } catch (InvalidKeyException e) {
            throw new RuntimeException("Could not check content", e);
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("Could not check content", e);
        } catch (SignatureException e) {
            throw new RuntimeException("Could not check content", e);
        }
    }

    /**
     * ?content
     * 
     * @throws RuntimeException
     */
    private byte[] getBytes(String content, String charset) throws RuntimeException {
        try {
            if (charset == null || "".equals(charset)) {
                charset = new OutputStreamWriter(new ByteArrayOutputStream()).getEncoding();
                charset = Charset.forName(charset).name();
            }
            return content.getBytes(charset);
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException("Invalid charset: " + charset, e);
        }
    }

    private class KeyPairEntry {

        private PublicKey publicKey;
        private PrivateKey privateKey;
    }
}