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

cn.bif.module.encryption.key.PrivateKeyManager Maven / Gradle / Ivy

The newest version!
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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.
 * © COPYRIGHT 2021 Corporation CAICT All rights reserved.
 * http://www.caict.ac.cn
 */
package cn.bif.module.encryption.key;

import cn.bif.exception.EncException;
import cn.bif.module.encryption.model.KeyMember;
import cn.bif.module.encryption.model.KeyType;
import cn.bif.utils.base.Base58;
import cn.bif.utils.hex.HexFormat;
import cn.bif.utils.sm2.SM2;
import cn.bif.utils.sm2.SM2KeyPair;
import net.i2p.crypto.eddsa.EdDSAEngine;
import net.i2p.crypto.eddsa.EdDSAPrivateKey;
import net.i2p.crypto.eddsa.EdDSAPublicKey;
import net.i2p.crypto.eddsa.KeyPairGenerator;
import net.i2p.crypto.eddsa.spec.EdDSANamedCurveTable;
import net.i2p.crypto.eddsa.spec.EdDSAParameterSpec;
import net.i2p.crypto.eddsa.spec.EdDSAPrivateKeySpec;
import net.i2p.crypto.eddsa.spec.EdDSAPublicKeySpec;
import org.bouncycastle.math.ec.ECPoint;

import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.security.*;

public class PrivateKeyManager {
    private PublicKeyManager publicKey = new PublicKeyManager();
    private KeyMember keyMember = new KeyMember();

    /**
     * generate key pair (default: ed25519)
     *
     * @throws EncException
     */
    public PrivateKeyManager() throws EncException {
        this(KeyType.ED25519);
    }

    public PrivateKeyManager(boolean isDefault, String chainCode) throws EncException {
        this(KeyType.ED25519, chainCode);
    }

    /**
     * generate key pair
     *
     * @param type the type of key
     * @throws EncException
     */
    public PrivateKeyManager(KeyType type) throws EncException {
        switch (type) {
            case ED25519: {
                KeyPairGenerator keyPairGenerator = new KeyPairGenerator();
                KeyPair keyPair = keyPairGenerator.generateKeyPair();
                EdDSAPrivateKey priKey = (EdDSAPrivateKey) keyPair.getPrivate();
                EdDSAPublicKey pubKey = (EdDSAPublicKey) keyPair.getPublic();
                keyMember.setRawSKey(priKey.getSeed());
                publicKey.setRawPublicKey(pubKey.getAbyte());
                break;
            }
            case SM2: {
                SM2KeyPair keyPair = SM2.getSM2KeyPair();
                byte[] rawSkey = SM2.getRawSkey(keyPair);
                byte[] rawPubKey = SM2.getRawPubKey(keyPair);
                keyMember.setRawSKey(rawSkey);
                publicKey.setRawPublicKey(rawPubKey);
                break;
            }
            default:
                throw new EncException("type does not exist");
        }
        setKeyType(type);
        publicKey.setKeyType(type);
    }

    /**
     * generate key pair
     *
     * @param type the type of key
     * @throws EncException
     */
    public PrivateKeyManager(KeyType type, String chainCode) throws EncException {
        switch (type) {
            case ED25519: {
                KeyPairGenerator keyPairGenerator = new KeyPairGenerator();
                KeyPair keyPair = keyPairGenerator.generateKeyPair();
                EdDSAPrivateKey priKey = (EdDSAPrivateKey) keyPair.getPrivate();
                EdDSAPublicKey pubKey = (EdDSAPublicKey) keyPair.getPublic();
                keyMember.setRawSKey(priKey.getSeed());
                publicKey.setRawPublicKey(pubKey.getAbyte());
                publicKey.setChainCode(chainCode);
                break;
            }
            case SM2: {
                SM2KeyPair keyPair = SM2.getSM2KeyPair();
                byte[] rawSkey = SM2.getRawSkey(keyPair);
                byte[] rawPubKey = SM2.getRawPubKey(keyPair);
                keyMember.setRawSKey(rawSkey);
                publicKey.setRawPublicKey(rawPubKey);
                publicKey.setChainCode(chainCode);
                break;
            }
            default:
                throw new EncException("type does not exist");
        }
        setKeyType(type);
        publicKey.setKeyType(type);
    }

    /**
     * generate key pair
     *
     * @param seed the seed
     */
    public PrivateKeyManager(byte[] seed, KeyType type) {
        switch (type) {
            case ED25519: {
                EdDSAParameterSpec spec = EdDSANamedCurveTable.getByName("ed25519-sha-512");
                EdDSAPrivateKeySpec privKey = new EdDSAPrivateKeySpec(seed, spec);
                EdDSAPublicKeySpec spec2 = new EdDSAPublicKeySpec(privKey.getA(), spec);
                EdDSAPublicKey pDsaPublicKey = new EdDSAPublicKey(spec2);
                publicKey.setRawPublicKey(pDsaPublicKey.getAbyte());
                keyMember.setRawSKey(seed);
                setKeyType(KeyType.ED25519);
                publicKey.setKeyType(KeyType.ED25519);
                break;
            }
            case SM2: {
                keyMember.setRawSKey(seed);
                setKeyType(KeyType.SM2);
                break;
            }
            default:
                throw new EncException("type does not exist");
        }
    }

    public PrivateKeyManager(byte[] seed) {
        EdDSAParameterSpec spec = EdDSANamedCurveTable.getByName("ed25519-sha-512");
        EdDSAPrivateKeySpec privKey = new EdDSAPrivateKeySpec(seed, spec);
        EdDSAPublicKeySpec spec2 = new EdDSAPublicKeySpec(privKey.getA(), spec);
        EdDSAPublicKey pDsaPublicKey = new EdDSAPublicKey(spec2);
        publicKey.setRawPublicKey(pDsaPublicKey.getAbyte());
        keyMember.setRawSKey(seed);
        setKeyType(KeyType.ED25519);
        publicKey.setKeyType(KeyType.ED25519);
    }

    /**
     * generate key pair
     *
     * @param skey private key
     * @throws EncException
     */
    public PrivateKeyManager(String skey) throws EncException {
        getPrivateKey(skey, keyMember);
        publicKey.setKeyType(keyMember.getKeyType());
        byte[] rawPKey = getPublicKey(keyMember);
        publicKey.setRawPublicKey(rawPKey);
        keyMember.setRawPKey(rawPKey);
    }

    public PrivateKeyManager(String skey, String chainCode) throws EncException {
        getPrivateKey(skey, keyMember);
        publicKey.setKeyType(keyMember.getKeyType());
        byte[] rawPKey = getPublicKey(keyMember);
        publicKey.setRawPublicKey(rawPKey);
        keyMember.setRawPKey(rawPKey);
        publicKey.setChainCode(chainCode);
    }

    /**
     * set key type
     *
     * @param keyType key type
     */
    public void setKeyType(KeyType keyType) {
        keyMember.setKeyType(keyType);
    }

    /**
     * get key type
     *
     * @return key type
     */
    public KeyType getKeyType() {
        return keyMember.getKeyType();
    }

    /**
     * set raw private key
     *
     * @param rawSKey private key
     */
    public void setRawPrivateKey(byte[] rawSKey) {
        keyMember.setRawSKey(rawSKey);
    }

    /**
     * get raw private key
     *
     * @return raw private key
     */
    public byte[] getRawPrivateKey() {
        return keyMember.getRawSKey();
    }

    /**
     * 获取原生公钥
     *
     * @return
     */
    public byte[] getRawPublicKey() {
        return publicKey.getRawPublicKey();
    }

    /**
     * get public key
     *
     * @return public key
     */
    public PublicKeyManager getPublicKey() {
        return publicKey;
    }

    /**
     * @return encode private key
     * @throws EncException
     */
    public String getEncPrivateKey() throws EncException {
        byte[] rawSKey = keyMember.getRawSKey();
        if (rawSKey == null) {
            throw new EncException("raw private key is null");
        }
        return getEncPrivateKey(keyMember.getRawSKey(), keyMember.getKeyType());
    }

    /**
     * @param encPrivateKey encode private key
     * @return true or false
     */
    public static boolean isPrivateKeyValid(String encPrivateKey) {
        return encPrivateKeyValid(encPrivateKey);
    }


    /**
     * @return encode public key
     * @throws EncException
     */
    public String getEncPublicKey() throws EncException {
        byte[] rawPKey = publicKey.getRawPublicKey();
        if (rawPKey == null) {
            throw new EncException("raw public key is null");
        }
        return encPublicKey(keyMember.getKeyType(), rawPKey).toLowerCase();
    }

    /**
     * @param skey encode private key
     * @return encode public key
     * @throws EncException
     */
    public static String getEncPublicKey(String skey) throws EncException {
        KeyMember member = new KeyMember();
        getPrivateKey(skey, member);
        byte[] rawPKey = getPublicKey(member);
        return encPublicKey(member.getKeyType(), rawPKey).toLowerCase();
    }

    /**
     * 原生转星火公钥
     *
     * @param rawPKey
     * @param type
     * @return
     */
    public static String getEncPublicKey(byte[] rawPKey, KeyType type) {
        return encPublicKey(type, rawPKey).toLowerCase();
    }

    /**
     * @param encPublicKey encode public key
     * @return true or false
     */
    public static boolean isPublicKeyValid(String encPublicKey) {
        return PublicKeyManager.isPublicKeyValid(encPublicKey);
    }

    /**
     * @return encode address
     * @throws EncException getEncAddress
     */
    public String getEncAddress() throws EncException {
        return publicKey.getEncAddress();
    }

    /**
     * @param pKey encode public key
     * @return encode address
     * @throws EncException
     */
    public static String getEncAddress(String pKey, String chainCode) throws EncException {
        return PublicKeyManager.getEncAddress(pKey, chainCode);
    }

    /**
     * @param pKey encode public key
     * @return encode address
     * @throws EncException
     */
    public static String getEncAddress(String pKey) throws EncException {
        return PublicKeyManager.getEncAddress(pKey);
    }

    /**
     * @param encAddress encode address
     * @return true or false
     */
    public static boolean isAddressValid(String encAddress) {
        return PublicKeyManager.isAddressValid(encAddress);
    }

    /**
     * sign message
     *
     * @param msg message
     * @return sign data
     * @throws EncException
     */
    public byte[] sign(byte[] msg) throws EncException {
        return signMessage(msg, keyMember);
    }

    /**
     * sign message
     *
     * @param msg  message
     * @param skey private key
     * @return sign data
     * @throws EncException
     */
    public static byte[] sign(byte[] msg, String skey) throws EncException {
        KeyMember member = new KeyMember();
        getPrivateKey(skey, member);
        byte[] rawPKey = getPublicKey(member);
        member.setRawPKey(rawPKey);
        return signMessage(msg, member);
    }

    private static void getPrivateKey(String bSkey, KeyMember member) throws EncException {
        try {
            if (null == bSkey) {
                throw new EncException("Private key cannot be null");
            }

            byte[] skeyTmp = Base58.decode(bSkey);
            if (skeyTmp.length <= 5) {
                throw new EncException("Private key (" + bSkey + ") is invalid");
            }

            KeyType type;
            switch (skeyTmp[3]) {
                case KeyType.ED25519_VALUE: {
                    type = KeyType.values()[0];
                    break;
                }
                case KeyType.SM2_VALUE: {
                    type = KeyType.values()[1];
                    break;
                }
                default:
                    throw new EncException("Private key (" + bSkey + ") is invalid");

            }

            if (skeyTmp[4] != Base58.BASE_58_VALUE) {
                throw new EncException("Private key (" + bSkey + ") is invalid");
            }

            byte[] rawSKey = new byte[skeyTmp.length - 5];
            System.arraycopy(skeyTmp, 5, rawSKey, 0, rawSKey.length);

            member.setKeyType(type);
            member.setRawSKey(rawSKey);
        } catch (Exception e) {
            throw new EncException("Invalid privateKey");
        }

    }

    private static byte[] getPublicKey(KeyMember member) throws EncException {
        byte[] rawPKey = null;
        switch (member.getKeyType()) {
            case ED25519: {
                EdDSAParameterSpec spec = EdDSANamedCurveTable.getByName("ed25519-sha-512");
                EdDSAPrivateKeySpec privKey = new EdDSAPrivateKeySpec(member.getRawSKey(), spec);
                EdDSAPublicKeySpec spec2 = new EdDSAPublicKeySpec(privKey.getA(), spec);
                EdDSAPublicKey pDsaPublicKey = new EdDSAPublicKey(spec2);
                rawPKey = pDsaPublicKey.getAbyte();
                break;
            }
            case SM2: {
                BigInteger priKey = new BigInteger(member.getRawSKey());
                priKey = SM2.bigIntegerPreHandle(priKey);
                ECPoint pubKey = SM2.G.multiply(priKey).normalize();
                rawPKey = SM2.getRawPubKey(pubKey);
                break;
            }
            default:
                throw new EncException("Type does not exist");
        }
        return rawPKey;
    }

    /**
     * 原生转星火私钥
     *
     * @param type
     * @param raw_skey
     * @return
     * @throws EncException
     */
    public static String getEncPrivateKey(byte[] raw_skey, KeyType type) throws EncException {
        if (null == raw_skey) {
            throw new EncException("Private key is null");
        }
        byte[] buff = new byte[raw_skey.length + 5];
        buff[0] = (byte) 0x18;
        buff[1] = (byte) 0x9E;
        buff[2] = (byte) 0x99;
        System.arraycopy(raw_skey, 0, buff, 5, raw_skey.length);

        switch (type) {
            case ED25519: {
                buff[3] = KeyType.ED25519_VALUE;
                break;
            }
            case SM2: {
                buff[3] = KeyType.SM2_VALUE;
                break;
            }
            default:
                throw new EncException("type does not exist");
        }

        buff[4] = Base58.BASE_58_VALUE;

        return Base58.encode(buff);
    }

    private static boolean encPrivateKeyValid(String encPrivateKey) {
        boolean valid;
        try {
            if (null == encPrivateKey) {
                throw new EncException("Invalid privateKey");
            }

            byte[] privateKeyTemp = Base58.decode(encPrivateKey);

            if (privateKeyTemp.length != 37 || privateKeyTemp[0] != (byte) 0x18 || privateKeyTemp[1] != (byte) 0x9E ||
                    privateKeyTemp[2] != (byte) 0x99 || privateKeyTemp[4] != Base58.BASE_58_VALUE) {
                throw new EncException("Invalid privateKey");
            }

            switch (privateKeyTemp[3]) {
                // Ed25519算法 && SM2算法
                case KeyType.ED25519_VALUE:
                case KeyType.SM2_VALUE: {
                    break;
                }
                default:
                    throw new EncException("Invalid privateKey");
            }

            valid = true;
        } catch (Exception e) {
            valid = false;
        }
        return valid;
    }

    private static String encPublicKey(KeyType type, byte[] raw_pkey) throws EncException {
        if (null == raw_pkey) {
            throw new EncException("Public key is null");
        }
        int length = raw_pkey.length + 3;
        byte[] buff = new byte[length];
        buff[0] = (byte) 0xB0;

        switch (type) {
            case ED25519: {
                buff[1] = KeyType.ED25519_VALUE;
                break;
            }
            case SM2: {
                buff[1] = KeyType.SM2_VALUE;
                break;
            }
            default:
                throw new EncException("type does not exist");
        }

        buff[2] = Base58.BASE_58_VALUE;

        System.arraycopy(raw_pkey, 0, buff, 3, raw_pkey.length);

        return HexFormat.byteToHex(buff);
    }

    private static byte[] signMessage(byte[] msg, KeyMember member) throws EncException {
        if (null == member.getRawSKey()) {
            throw new EncException("Raw private key is null");
        }
        byte[] signMsg = null;

        try {
            switch (member.getKeyType()) {
                case ED25519: {
                    Signature sgr = new EdDSAEngine(MessageDigest.getInstance("SHA-512"));
                    EdDSAParameterSpec spec = EdDSANamedCurveTable.getByName("ed25519-sha-512");
                    EdDSAPrivateKeySpec sKeySpec = new EdDSAPrivateKeySpec(member.getRawSKey(), spec);
                    EdDSAPrivateKey sKey = new EdDSAPrivateKey(sKeySpec);
                    sgr.initSign(sKey);
                    sgr.update(msg);

                    signMsg = sgr.sign();
                    break;
                }
                case SM2: {
                    BigInteger sKey = new BigInteger(member.getRawSKey());
                    sKey = SM2.bigIntegerPreHandle(sKey);
                    SM2KeyPair keyPair = new SM2KeyPair(SM2.G.multiply(sKey).normalize(), sKey);
                    signMsg = SM2.signWithBytes(new String(msg, "ISO_8859_1"), "1234567812345678", keyPair);
                    break;
                }
                default:
                    throw new EncException("Type does not exist");
            }
        } catch (NoSuchAlgorithmException e) {
            throw new EncException("System error");
        } catch (InvalidKeyException e) {
            throw new EncException("Invalid privateKey");
        } catch (SignatureException e) {
            throw new EncException("Sign message failed");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }

        return signMsg;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy