1. 程式人生 > >區塊鏈基礎:非對稱演算法

區塊鏈基礎:非對稱演算法

這裡寫圖片描述

1.Hash演算法

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()); } }
1163a12be8b90e692445a7115ca900f4
c7a8233d922f3db03f1c7a0864675cb5092ce850d033b7ea07ca5208da27edfe
b286928d476b4de0aa5b8c83b7b27e54

2、RSA非對稱演算法

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);
    }
}
公鑰:
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 的父類

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);
    }
}