前一天有提到共用金钥密码系统(Shared-key CryptoSystem),又称为「对称密钥演算法」(Symmetric-key algorithm),稍微复习一下,Shared-key CryptoSystem是公钥与私钥为同一把「key」的系统,安全性相较於今天所提到的Public-key Cryptosystem来得低。
公开金钥密码系统(Public-key Cryptosystem)又称为非对称式密码学(Asymmetric cryptography)。与前一天提到的共同金钥密码系统不同,他拥有两把「key」,分别用於加密(公钥,Publickey)与解密(私钥,Privatekey),安全性比共同金钥密码来得高,看看下图:
从上图可以看到,公钥与私钥非同一把,有心人士拿到了公钥,也无法解读讯息,大大加深了安全性。
公钥(Publickey)与私钥(Privatekey)为一组,Publickey加密後,必须有对应的Privatekey才能进行解密。
优点:安全性高,仅拿到Publickey是无法解密。
缺点:加密和解密花费时间长、速度慢,只适合对少量资料进行加密。不适用於连续传输零碎数据的情况,若要解决连续传输零碎数据,解决方法是使用「混成密码系统」
关於公开金钥可信度问题的成因是,A无法判断接收到的公开金钥制作者是否为为B,需要利用「数位凭证」。关於「数位凭证」,之後会有进一步探讨。
公开金钥密码系统使用的演算法为「RSA加密」和「椭圆曲线密码学」(elliptic-curve cryptography),接下来我们来看看使用Python和JavaScript如何实现:
要找出实现公开金钥密码系统演算法必要条件:
产生RSA 金钥:
from Crypto.PublicKey import RSA
# 产生 2048 位元 RSA 金钥
key = RSA.generate(2048)
# RSA 私钥
privateKey = key.export_key()
with open("private.pem", "wb") as f:
f.write(privateKey)
# RSA 公钥
publicKey = key.publickey().export_key()
with open("public.pem", "wb") as f:
f.write(publicKey)
读取 RSA 金钥:
from Crypto.PublicKey import RSA
# 读取
encodedKey = open("private.pem", "rb").read()
# 解密
key = RSA.import_key(encodedKey)
# 输出 RSA 私钥
print(key.export_key().decode('utf-8'))
print(key.publickey().export_key().decode('utf-8'))
RSA 金钥解密资料:
from Crypto.PublicKey import RSA
from Crypto.Cipher import AES, PKCS1_OAEP
# 读取 RSA 私钥
privateKey = RSA.import_key(open("private.pem").read())
# 从档案读取加密资料
with open("encrypted_data.bin", "rb") as f:
encSessionKey = f.read(privateKey.size_in_bytes())
nonce = f.read(16)
tag = f.read(16)
ciphertext = f.read(-1)
# 以 RSA 金钥解密 Session 金钥
cipherRSA = PKCS1_OAEP.new(privateKey)
sessionKey = cipherRSA.decrypt(encSessionKey)
# 以 AES Session 金钥解密资料
cipherAES = AES.new(sessionKey, AES.MODE_EAX, nonce)
data = cipherAES.decrypt_and_verify(ciphertext, tag)
# 输出解密後的资料
print(data.decode("utf-8"))
安装node.js後,在安装npm,利用npm安装下列库:
npm install tweetnacl tweetnacl-util
//import the libraries
const nacl = require('tweetnacl');
nacl.util = require('tweetnacl-util');
//Generate the keys
const david = nacl.box.keyPair();
const viktoria = nacl.box.keyPair();
//encrypting the message
function davidEncrypting(){
const one_time_code = nacl.randomBytes(24);
//Get the message from david
const plain_text = "Hello there Viktoria";
//Get the cipher text
const cipher_text = nacl.box(
nacl.util.decodeUTF8(plain_text),
one_time_code,
viktoria.publicKey,
david.secretKey
);
//message to be sent to Viktoria
const message_in_transit = {cipher_text,one_time_code};
return message_in_transit;
};
//decrypting the message
function viktoriaDecrypting(message){
//Get the decoded message
let decoded_message = nacl.box.open(message.cipher_text, message.one_time_code, david.publicKey, viktoria.secretKey);
//Get the human readable message
let plain_text = nacl.util.encodeUTF8(decoded_message)
//return the plaintext
return plain_text;
};
参考资料:Implementing Public Key Cryptography in JavaScript
>>: [CodeIgniter 3] 记忆体的隐形杀手:Log all queries
回呼函式 所谓回呼函式(callback function)与一般函式基本相同,差别在於它须「具一定...
在 gradle (Module) 层级的 dependencies 中内加入: implement...
(不写code,有点不懂但看起来超酷的呈现方式) 先小小悼念一下作者伊藤计划,天才英年早逝,如果仍...
前言 非同步一直是困扰着 Javascript 新手的小魔王,以前常常会有「为什麽这行先跑到没有先执...
上一篇介绍了2 the 9s,是一题会需要重复执行的题目,使用回圈跟副程序会比较容易执行,整体上不会...