秒懂区块链核心技术之非对称加密

Posted 工匠小猪猪的技术世界

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了秒懂区块链核心技术之非对称加密相关的知识,希望对你有一定的参考价值。

当前浏览器不支持播放音乐或语音,请在微信或其他浏览器中播放 秒懂区块链核心技术之非对称加密 秒懂区块链核心技术之非对称加密


秒懂区块链核心技术之非对称加密
  1. 您对于源码的疑问每条留言都将得到认真回复。甚至不知道如何读源码也可以请教噢。

  2. 新的源码解析文章实时收到通知。每两周更新一篇左右。

总结

既然是加密,那肯定是不希望别人知道我的消息,所以只有我才能解密,所以可得出公钥负责加密,私钥负责解密;同理,既然是签名,那肯定是不希望有人冒充我发消息,只有我才能发布这个签名,所以可得出私钥负责签名,公钥负责验证。

本文完秒懂区块链核心技术之非对称加密


其实要点已经结束了,不尽兴?那我们继续温习一下

非对称加密算法

非对称加密是相对于对称加密而言的

对称加密:采用单钥密码系统的加密方法,同一个密钥可以同时用作信息的加密和解密,这种加密方法称为对称加密,也称为单密钥加密。所谓对称就是加密和解密的过程使用的是相同的密钥。

非对称加密技术是区块链核心技术之一,是保证区块链安全的基础技术。该技术含有两个密钥:公钥和私钥。具体操作如下:首先,系统按照某种密钥生成算法,经过计算得出私钥,然后用另一个算法根据私钥生成公钥,公钥的生成过程不可逆。由于在现有的计算能力条件下难以通过公钥来穷举出私钥,因此可以认为是具有密码学安全的,从而能够保证区块链的数据安全。非对称加密算法的保密性比较好,它消除了最终用户交换密钥的需要。

非对称加密算法需要两个密钥:公开密钥(publickey)和私有密钥(privatekey)。公开密钥与私有密钥是一对,如果用公开密钥对数据进行加密,只有用对应的私有密钥才能解密;如果用私有密钥对数据进行加密,那么只有用对应的公开密钥才能解密。因为加密和解密使用的是两个不同的密钥,所以这种算法叫作非对称加密算法。

如下图所示,甲乙之间使用非对称加密的方式完成了重要信息的安全传输。

秒懂区块链核心技术之非对称加密

1、乙方生成一对密钥(公钥和私钥)并将公钥向其它方公开。
2、得到该公钥的甲方使用该密钥对机密信息进行加密后再发送给乙方。
3、乙方再用自己保存的另一把专用密钥(私钥)对加密后的信息进行解密。乙方只能用其专用密钥(私钥)解密由对应的公钥加密后的信息。
在传输过程中,即使攻击者截获了传输的密文,并得到了乙的公钥,也无法破解密文,因为只有乙的私钥才能解密密文。
同样,如果乙要回复加密信息给甲,那么需要甲先公布甲的公钥给乙用于加密,甲自己保存甲的私钥用于解密。

有人曾经画过这样的图来帮助理解:

非对称密码和对称加密的优缺点

对称加密,具体算法有:DES,3DES,TDEA,Blowfish,RC5,IDEA。常见的有:DES,AES,3DES等等。

优点:算法公开、计算量小、加密速度快、加密效率高。
缺点:秘钥的管理和分发非常困难,不够安全。在数据传送前,发送方和接收方必须商定好秘钥,然后双方都必须要保存好秘钥,如果一方的秘钥被泄露,那么加密信息也就不安全了。另外,每对用户每次使用对称加密算法时,都需要使用其他人不知道的唯一秘钥,这会使得收、发双方所拥有的钥匙数量巨大,密钥管理成为双方的负担。

非对称加密,具体算法有:RSA、Elgamal、背包算法、Rabin、HD,ECC(椭圆曲线加密算法)。常见的有:RSA,ECC。

缺点:算法强度复杂、安全性依赖于算法与密钥但是由于其算法复杂,而使得加密解密速度没有对称加密解密的速度快。
优点:对称密码体制中只有一种密钥,并且是非公开的,如果要解密就得让对方知道密钥。所以保证其安全性就是保证密钥的安全,而非对称密钥体制有两种密钥,其中一个是公开的,这样就可以不需要像对称密码那样传输对方的密钥了。这样安全性就大了很多。

例子

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import javax.crypto.Cipher;
import java.security.*;
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;

public class RSATest {

    public static final String KEY_ALGORTHM = "RSA";//
    public static final String SIGNATURE_ALGORITHM = "MD5withRSA";

    public static final String PUBLIC_KEY = "RSAPublicKey";//公钥
    public static final String PRIVATE_KEY = "RSAPrivateKey";//私钥

    /**
     * BASE64解密
     *
     * @param key
     * @return
     * @throws Exception
     */

    public static byte[] decryptBASE64(String key) throws Exception {
        return (new BASE64Decoder()).decodeBuffer(key);
    }

    /**
     * BASE64加密
     *
     * @param key
     * @return
     * @throws Exception
     */

    public static String encryptBASE64(byte[] key) throws Exception {
        return (new BASE64Encoder()).encodeBuffer(key);
    }


    /**
     * 初始化密钥
     *
     * @return
     * @throws Exception
     */

    public static Map<String, Object> initKey() throws Exception {
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(KEY_ALGORTHM);
        keyPairGenerator.initialize(1024);
        KeyPair keyPair = keyPairGenerator.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;
    }

    /**
     * 取得公钥,并转化为String类型
     *
     * @param keyMap
     * @return
     * @throws Exception
     */

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

    /**
     * 取得私钥,并转化为String类型
     *
     * @param keyMap
     * @return
     * @throws Exception
     */

    public static String getPrivateKey(Map<String, Object> keyMap) throws Exception {
        Key key = (Key) keyMap.get(PRIVATE_KEY);
        return encryptBASE64(key.getEncoded());
    }


    /**
     * 用公钥加密
     *
     * @param data 加密数据
     * @param key  密钥
     * @return
     * @throws Exception
     */

    public static byte[] encryptByPublicKey(byte[] data, String key) throws Exception {
        //对公钥解密
        byte[] keyBytes = decryptBASE64(key);
        //取公钥
        X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORTHM);
        Key publicKey = keyFactory.generatePublic(x509EncodedKeySpec);

        //对数据解密
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);

        return cipher.doFinal(data);
    }


    /**
     * 用私钥解密
     *
     * @param data 加密数据
     * @param key  密钥
     * @return
     * @throws Exception
     */

    public static byte[] decryptByPrivateKey(byte[] data, String key) throws Exception {
        //对私钥解密
        byte[] keyBytes = decryptBASE64(key);

        PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORTHM);
        Key privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
        //对数据解密
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.DECRYPT_MODE, privateKey);

        return cipher.doFinal(data);
    }


    /**
     * 用私钥对信息生成数字签名
     *
     * @param data       //加密数据
     * @param privateKey //私钥
     * @return
     * @throws Exception
     */

    public static String sign(byte[] data, String privateKey) throws Exception {
        //解密私钥
        byte[] keyBytes = decryptBASE64(privateKey);
        //构造PKCS8EncodedKeySpec对象
        PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(keyBytes);
        //指定加密算法
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORTHM);
        //取私钥匙对象
        PrivateKey privateKey2 = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
        //用私钥对信息生成数字签名
        Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
        signature.initSign(privateKey2);
        signature.update(data);

        return encryptBASE64(signature.sign());
    }


    /**
     * 校验数字签名
     *
     * @param data      加密数据
     * @param publicKey 公钥
     * @param sign      数字签名
     * @return
     * @throws Exception
     */

    public static boolean verify(byte[] data, String publicKey, String sign) throws Exception {
        //解密公钥
        byte[] keyBytes = decryptBASE64(publicKey);
        //构造X509EncodedKeySpec对象
        X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(keyBytes);
        //指定加密算法
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORTHM);
        //取公钥匙对象
        PublicKey publicKey2 = keyFactory.generatePublic(x509EncodedKeySpec);

        Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
        signature.initVerify(publicKey2);
        signature.update(data);
        //验证签名是否正常
        return signature.verify(decryptBASE64(sign));

    }

    public static void main(String[] args) {
        String content = "{name:幽冥诡匠,age:404,sex:man,address:鬼王墓}";

        //1.初始化公钥私钥
        String rsaPublicKey = null;
        String rsaPrivateKey = null;
        try {
            Map<String, Object> map = RSATest.initKey();
            rsaPublicKey = getPublicKey(map);
            rsaPrivateKey = getPrivateKey(map);
        } catch (Exception e) {
            e.printStackTrace();
        }

        //2.使用公钥加密
        try {
            System.out.println("加密前==" + content);
            byte[] result_m = RSATest.encryptByPublicKey(content.getBytes(), rsaPublicKey);
            content = encryptBASE64(result_m);
            System.out.println("加密后==" + content);
        } catch (Exception e) {
            e.printStackTrace();
        }
        //3.私钥解密
        try {
            byte[] b1 = decryptBASE64(content);
            byte[] b2 = decryptByPrivateKey(b1, rsaPrivateKey);
            content = new String(b2);
            System.out.println("解密后==" + content);
        } catch (Exception e) {
            e.printStackTrace();
        }


        //4.私钥加签
        String sign = null;
        try {
            sign = sign(content.getBytes(), rsaPrivateKey);
            System.out.println("签名==" + sign);
        } catch (Exception e) {
            e.printStackTrace();
        }
        //5.公钥验签
        try {
            boolean flag = verify(content.getBytes(), rsaPublicKey, sign);
            System.out.println("验签结果==" + flag);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

输出结果:

加密前=={name:幽冥诡匠,age:404,sex:man,address:鬼王墓}
加密后==geb6skp6voDS3Z2UR7OqUAdyMZbm87GCFwV03MTOIt+4UfHDUH5Nbi/2/RLrFBOr6y6gXLihG4gR
3PF6rWDqT4CNQenJkeAjdRD7Om8q1gFQ2G4aapQU3ccg49E5in1FruuGwy7Ui7EkUF2ts53YwNjY
dhVn7ilBOW4AuE0xtKo=

解密后=={name:幽冥诡匠,age:404,sex:man,address:鬼王墓}
签名==OXKhHxaadTuys91AXhOKe8d4fbinVva+wXLeTAIM1uFL+glaBIitULYhnref+h8SGuJox6BjRoXO
iVofsgiVwdQAKtgU/EbYr7199B3iT9BORNx8q39PD/sqC69z0W/JWLoZhd+RaZmO9klEQjYMqOy0
tjmNC3gEVxw4gxK98UM=

验签结果==true



以上是关于秒懂区块链核心技术之非对称加密的主要内容,如果未能解决你的问题,请参考以下文章

区块链词典 | 区块链核心技术之非对称加密算法

区块链核心算法之非对称加密技术

区块链技术之非对称加密算法

区块链技术创新之非对称加密算法

区块链之非对称加密算法

大橙大条国际视频:4分钟读懂~区块链底层加密算法之非对称加密