区块链基础:非对称算法

2022-05-06 19:51:23 浏览数 (1)

1.Hash算法

代码语言:javascript复制
package cn.hadron.security;

import java.security.MessageDigest;
import java.util.UUID;

import org.eclipse.jetty.util.security.Credential.MD5;

/**
 * crypto['krɪptoʊ]秘密成员,
 * 一些语言的crypto模块的目的是为了提供通用的加密和哈希算法
 * 加密工具类
 */
public class CryptoUtil {
    //工具类,隐藏构造器
    private CryptoUtil() {}

    /**
     * 计算给定字符串的SHA256值
     */
    public static String sha256(String str) {
        MessageDigest messageDigest;
        String hash = "";
        try {
            messageDigest = MessageDigest.getInstance("SHA-256");
            messageDigest.update(str.getBytes("UTF-8"));
            hash = byte2Hex(messageDigest.digest());
        } catch (Exception e) {
            System.out.println("getSHA256 is error"   e.getMessage());
        }
        return hash;
    }

    /**
     * 计算str的md5码(技巧:去除前几位,增强安全性)
     */
    public static String md5(String str) {
        String resultStr = MD5.digest(str);
        return resultStr.substring(4, resultStr.length());
    }

    /**
     * UUID的目的是让分布式系统中的所有元素都能有唯一的辨识
     * 获取一个UUID值,默认格式带有"-",需要删除所有的"-"
     */
    public static String getUUID() {
        return UUID.randomUUID().toString().replaceAll("\-", "");
    }

    /**
     * 二进制字节数据转换为十六进制字符串形式
     * @param bytes
     */
    private static String byte2Hex(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        String tmp;
        for (int i = 0; i < bytes.length; i  ) {
            /**
             * 注意toHexString(int i)的参数类型是32位int型,而传输入8位byte型数据会转换int型。
             * 转换后高24为也看作有效位,正数不影响,而负数会导致错误。
             * java中采用的是补码的形式表示负整数,比如byte的-1(0xff,11111111),会转换成int型的-1(0xffffffff),
             * 而oxff默认是int型,表示为0000 0000 0000 0000 0000 0000 1111 1111
             * 一个byte跟0xff &运算,高的24个比特就总会被清0,得到我们想要的结果。
             */
            tmp = Integer.toHexString(bytes[i] & 0xFF);
            if (tmp.length() == 1) {
                sb.append("0");
            }
            sb.append(tmp);
        }
        return sb.toString();
    }

    public static void main(String[] args){
        String s="chengyuqiang";
        System.out.println(CryptoUtil.md5(s));
        System.out.println(CryptoUtil.sha256(s));
        System.out.println(CryptoUtil.getUUID());
    }
}
代码语言:javascript复制
1163a12be8b90e692445a7115ca900f4
c7a8233d922f3db03f1c7a0864675cb5092ce850d033b7ea07ca5208da27edfe
b286928d476b4de0aa5b8c83b7b27e54

2、RSA非对称算法

代码语言:javascript复制
package cn.hadron.security;

import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;
import javax.crypto.Cipher;


/**
 * RSA安全编码组件
 */
public abstract class RsaUtil extends Coder {
    public static final String KEY_ALGORITHM = "RSA";
    public static final String SIGNATURE_ALGORITHM = "MD5withRSA";
    private static final String PUBLIC_KEY = "RSAPublicKey";
    private static final String PRIVATE_KEY = "RSAPrivateKey";

    /**
     * 初始化密钥
     */
    public static Map<String, Object> initKey() throws Exception {
        //RSA密钥对生成器
        KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(KEY_ALGORITHM);
        //初始化
        keyPairGen.initialize(1024);
        //耗时操作,动态生成密钥对
        KeyPair keyPair = keyPairGen.generateKeyPair();
        //获取公钥
        RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
        //获取私钥
        RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
        //保存密钥对
        Map<String, Object> keyMap = new HashMap<String, Object>(2);
        keyMap.put(PUBLIC_KEY, publicKey);
        keyMap.put(PRIVATE_KEY, privateKey);
        return keyMap;
    }
    /**
     * 取得私钥
     */
    public static String getPrivateKey(Map<String, Object> keyMap) throws Exception {
        Key key = (Key) keyMap.get(PRIVATE_KEY);
        return encryptBASE64(key.getEncoded());
    }

    /**
     * 取得公钥
     */
    public static String getPublicKey(Map<String, Object> keyMap) throws Exception {
        Key key = (Key) keyMap.get(PUBLIC_KEY);
        return encryptBASE64(key.getEncoded());
    }

    /*******************公钥加密,私钥解密**************************/

    /**
     * 消息发送者用对方公钥加密
     */
    public static byte[] encryptByPublicKey(byte[] data, String key) throws Exception {
        // 对公钥BASE64解密,取得公钥
        X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(decryptBASE64(key));
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        Key publicKey = keyFactory.generatePublic(x509KeySpec);

        // 对数据加密
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        //将Cipher初始化为加密模式
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        //数据将被加密或解密
        return cipher.doFinal(data);
    }
    /**
     * 消息接收者用自己的私钥解密
     */
    public static byte[] decryptByPrivateKey(byte[] data, String key) throws Exception {
        // decryptBASE64(key)对密钥解密,取得私钥
        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(decryptBASE64(key));
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        Key privateKey = keyFactory.generatePrivate(pkcs8KeySpec);
        // 对数据解密
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        //将Cipher初始化为解密模式
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        //数据将被加密或解密
        return cipher.doFinal(data);
    }

    /*******************秘钥加密,公钥验证***********************/

    /**
     * 消息发送者用自己的私钥加密
     */
    public static byte[] encryptByPrivateKey(byte[] data, String key) throws Exception {
        // 对密钥解密,取得私钥
        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(decryptBASE64(key));
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        Key privateKey = keyFactory.generatePrivate(pkcs8KeySpec);
        // 对数据加密
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        //加密模式
        cipher.init(Cipher.ENCRYPT_MODE, privateKey);
        return cipher.doFinal(data);
    }
    /**
     * 用公钥解密
     */
    public static byte[] decryptByPublicKey(byte[] data, String key) throws Exception {
        //对密钥解密, 取得公钥
        X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(decryptBASE64(key));
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        Key publicKey = keyFactory.generatePublic(x509KeySpec);
        // 对数据解密
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        //解密模式
        cipher.init(Cipher.DECRYPT_MODE, publicKey);
        return cipher.doFinal(data);
    }

    /****************数字签名:私钥加密,公钥验证**********************/

    /**
     * 用发送者的私钥对信息生成数字签名
     * @param data : 加密数据
     * @param privateKey: 私钥
     */
    public static String sign(byte[] data, String privateKey) throws Exception {
        // 解密由base64编码的私钥,构造PKCS8EncodedKeySpec对象
        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(decryptBASE64(privateKey));
        //指定的加密算法RSA
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        //取私钥匙对象
        PrivateKey priKey = keyFactory.generatePrivate(pkcs8KeySpec);
        //Signature类用来提供数字签名算法功能
        //可以将签名算法指定为 MD2withRSA、MD5withRSA 或 SHA1withRSA
        Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
        //用私钥初始化这个用于签名的对象
        signature.initSign(priKey);
        //使用指定的byte数组更新要签名或验证的数据
        signature.update(data);
        //sign()返回已更新数据的签名字节,再进行BASE64加密
        return encryptBASE64(signature.sign());
    }

    /**
     * 使用发送者的公钥校验数字签名
     * 通过发送者的公钥publicKey验证他签名内容sign是否符合data数据
     * @param data: 加密数据
     * @param publicKey: 公钥
     * @param sign: 数字签名
     * @return 校验成功返回true 失败返回false
     */
    public static boolean verify(byte[] data, String publicKey, String sign) throws Exception {
        // 解密由base64编码的公钥,构造X509EncodedKeySpec对象
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(decryptBASE64(publicKey));
        // 指定加密算法RSA
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        // 取公钥匙对象
        PublicKey pubKey = keyFactory.generatePublic(keySpec);
        //Signature类用来提供数字签名算法功能
        Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
        //用公钥初始化验证对象
        signature.initVerify(pubKey);
        //使用指定的byte数组更新要签名或验证的数据
        signature.update(data);
        // 验证签名是否正常
        return signature.verify(decryptBASE64(sign));
    }

    public static void main(String[] args) throws Exception{
        String s="chengyuqiang";
        /**
         * 测试公钥加密,私有解密
         */
        Map<String, Object> map=RsaUtil.initKey();
        String publicKey=RsaUtil.getPublicKey(map);
        String privateKey=RsaUtil.getPrivateKey(map);
        System.out.println("公钥:n" publicKey);
        System.out.println("私钥:n" privateKey);
        //公钥加密
        byte[] msg=RsaUtil.encryptByPublicKey(s.getBytes(), publicKey);
        //秘钥解密
        msg=RsaUtil.decryptByPrivateKey(msg, privateKey);
        System.out.println("解密:n" new String(msg));

        /**
         * 测试私签名,公钥验证签名
         */
        // 产生签名
        String sign = RsaUtil.sign(s.getBytes(), privateKey);
        System.out.println("签名内容:n" sign);
        //验证签名
        boolean status = RsaUtil.verify(s.getBytes(), publicKey, sign);
        System.out.println("签名正确:n" status);
    }
}
代码语言:javascript复制
公钥:
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC2N1dAK2NzzcOjRwb3rBjT NvpMKKgL98Pr3D0
jE99hfJL2MpuKflA0U18EKnZT1QjrninAeLHiR1BlnuJpHVGKNPkzXuIhggiHlvdb9WwsfB u pf
Igca7cURYR 4bELE hlUVP8nyMuD9Vs8bY23oHG2Ff/svVQEo/j4uOMAywIDAQAB

私钥:
MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBALY3V0ArY3PNw6NHBvesGNP42 kw
oqAv3w vcPSMT32F8kvYym4p UDRTXwQqdlPVCOueKcB4seJHUGWe4mkdUYo0 TNe4iGCCIeW91v
1bCx8H676l8iBxrtxRFhH7hsQsT6GVRU/yfIy4P1WzxtjbegcbYV/ y9VASj Pi44wDLAgMBAAEC
gYBOOEFvHXEK1CiIXcQi67CYxfp5BtS42PPzQsfFYrn401gosP5s/f2ukmqluG2BCKnAy3OllYyp
RTXW4udTNdLVOiglX5TSCk1zp3Hn6oLbbjWIpoqAhx5PJslZY35MscNYVViz69FwLHjCeDWRitsV
f/eDHyC r6vb3PQTgpjegQJBAOvtWqLhMNhAOel14pirf A520xz/gzpSj/dCzTS53oLGvCJqzn1
HJqA4xmhEf8MMcHN4 SiVtjQdKVINaFbeUECQQDFuCBzCMLKHNfrUp35lOlnmAT5RBEU 0CV85jl
oERpLTU1v6igsP6mxXJXXRQpNzP2orN1IbrVVwF8uuUU/wsLAkBiDtH4Fs69YtxvG08mE0ngAUwT
l7ZE2YXBy3bH6szI3erBhQbE3QqZcO5zDY40SnY3zgJlWc/s559DvyKDQUjBAkEAqa7filnWcgZW
98orcWpu9Uzt186mqk8Gmqo4abklfO4jYEFfwqijoxSIkJl9F/IcUmpHgRq1cSn SMFMoLxRCQJA
PJFE5keSZgjJpGsMAdEIpHKKUxF5vd oS9 Z7EpSn7VGTRPLycSIDKQT2F9/QV1z5IKni1jqbnXs
imRw1coviw==

解密:
chengyuqiang
签名内容:
BqJgQ4ciZNH0bE0TQeTgQQbF h0jPNauHbgc95L8QggwD0p8qb4fdEjsmevdiN0OszOqyR9z71S9
LXCeH ZeKVZagRWG0jx0Bfk74Rf5Pt2MMPqjzlDRfCTJyg0z8GjC/U70IaxgfgkrFVf3rsk4XzAB
R045Sjf2P nJf/hf4wE=

签名正确:
true

3、RsaUtil 的父类

代码语言:javascript复制
package cn.hadron.security;

import java.security.MessageDigest;
import javax.crypto.KeyGenerator;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

/**
 * 基础加密组件
 * 
 */
public abstract class Coder {
    public static final String KEY_SHA = "SHA";
    public static final String KEY_MD5 = "MD5";
    //HMAC(Hash Message Authentication Code),散列消息鉴别码,基于密钥的Hash算法的认证协议
    public static final String KEY_MAC = "HmacMD5";

    //BASE64实现主要就是BASE64Encoder、BASE64Decoder两个类,我们只需要知道使用对应的方法即可。

    /**
     * BASE64加密,把任意序列的8位字节描述为一种不易被人直接识别的形式。
     * BASE加密后产生的字节位数是8的倍数,如果不够位数以=符号填充
     */
    public static String encryptBASE64(byte[] key) throws Exception {
        return (new BASE64Encoder()).encodeBuffer(key);
    }
    /**
     * BASE64解密
     */
    public static byte[] decryptBASE64(String key) throws Exception {
        return (new BASE64Decoder()).decodeBuffer(key);
    }

    /**
     * JDK提供的MD5算法实现
     */
    public static byte[] encryptMD5(byte[] data) throws Exception {
        MessageDigest md5 = MessageDigest.getInstance(KEY_MD5);
        md5.update(data);
        return md5.digest();
    }

    /**
     * JDK提供的SHA算法
     */
    public static byte[] encryptSHA(byte[] data) throws Exception {
        MessageDigest sha = MessageDigest.getInstance(KEY_SHA);
        sha.update(data);
        return sha.digest();

    }

    /**
     * 初始化HMAC密钥
     */
    public static String initMacKey() throws Exception {
        KeyGenerator keyGenerator = KeyGenerator.getInstance(KEY_MAC);
        SecretKey secretKey = keyGenerator.generateKey();
        return encryptBASE64(secretKey.getEncoded());
    }

    /**
     * HMAC加密
     */
    public static byte[] encryptHMAC(byte[] data, String key) throws Exception {
        SecretKey secretKey = new SecretKeySpec(decryptBASE64(key), KEY_MAC);
        Mac mac = Mac.getInstance(secretKey.getAlgorithm());
        mac.init(secretKey);
        return mac.doFinal(data);
    }
}

0 人点赞