秒懂区块链核心技术之非对称加密
Posted 工匠小猪猪的技术世界
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了秒懂区块链核心技术之非对称加密相关的知识,希望对你有一定的参考价值。
您对于源码的疑问每条留言都将得到认真回复。甚至不知道如何读源码也可以请教噢。
新的源码解析文章实时收到通知。每两周更新一篇左右。
总结
既然是加密,那肯定是不希望别人知道我的消息,所以只有我才能解密,所以可得出公钥负责加密,私钥负责解密;同理,既然是签名,那肯定是不希望有人冒充我发消息,只有我才能发布这个签名,所以可得出私钥负责签名,公钥负责验证。
本文完
其实要点已经结束了,不尽兴?那我们继续温习一下
非对称加密算法
非对称加密是相对于对称加密而言的
对称加密:采用单钥密码系统的加密方法,同一个密钥可以同时用作信息的加密和解密,这种加密方法称为对称加密,也称为单密钥加密。所谓对称就是加密和解密的过程使用的是相同的密钥。
非对称加密技术是区块链核心技术之一,是保证区块链安全的基础技术。该技术含有两个密钥:公钥和私钥。具体操作如下:首先,系统按照某种密钥生成算法,经过计算得出私钥,然后用另一个算法根据私钥生成公钥,公钥的生成过程不可逆。由于在现有的计算能力条件下难以通过公钥来穷举出私钥,因此可以认为是具有密码学安全的,从而能够保证区块链的数据安全。非对称加密算法的保密性比较好,它消除了最终用户交换密钥的需要。
非对称加密算法需要两个密钥:公开密钥(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
以上是关于秒懂区块链核心技术之非对称加密的主要内容,如果未能解决你的问题,请参考以下文章