在JavaScript中实现公钥密码学
密码学是指对信息进行编码和解码,以保持信息在传输过程中的保密性、完整性和认证。公钥密码学也被称为非对称密码学。在这种方法中,有一个公钥和一个私钥。公钥广为人知,而私钥则是一对通信者的秘密。
当一对人要进行通信时,发送者使用接收者的公钥对信息进行加密,从而得到密码文本。当收件人收到信息时,他们用他们的私钥解密信息。发送方的私钥和接收方的公钥被编码在密码文本中。这就消除了[密钥分配问题]。
前提条件
在我们开始之前,如果你有以下条件,将有所帮助。
-
在你的电脑上安装Node.js。
-
一些关于JavaScript编程语言的基本知识。
-
一些关于密码学的基本知识。
使用公钥密码学的算法
自1976年首次发布以来,不同的算法都应用了这种机制。以下是一些使用公钥密码学的算法。
-
RSA(Rivest-Shamir-Adelman):RSA是由[Rivest],[Shamir]和[Adelman]设计的。
-
椭圆曲线加密法:椭圆曲线加密法是由[Neal Koblitz]和[Victor S. miller]在1985年提出的。它是基于椭圆曲线有限域上的[代数结构]。
-
Diffie Hellman协议:Diffie Hellman协议是一种使用[公共通道]交换加密密钥的机制。它是由[Whitfield Diffie]和[Martin Hellman]设计的,并在1976年首次发表。
JavaScript中的公钥密码学库
有不同的库用于在JavaScript中实现公钥密码学。以下是最常用的。
-
[NaCL]:它是一个高速库,用于进行加密、解密和网络通信。它使用椭圆曲线密码学算法。
-
[TweetNaCL]:它是最早发布的加密库之一,它最初是用C编程语言编写的。TweeNaCL.js是该库的JavaScript版本。它使用Diffie Hellman算法。
使用TweetNaCL.js来实现公钥加密技术
在这篇文章中,我们将使用TweetNaCL.js
来实现公钥密码学的概念。
首先,让我们安装应用程序中使用的依赖项。你可以使用npm
或 yarn
来安装这些软件包。
npm install tweetnacl tweetnacl-util
或
yarn add tweetnacl tweetnacl-util
实际场景
我们有两个通信对,David和Viktoria。当David向Viktoria发送消息时,他使用Viktoria的公钥对其进行加密。当Viktoria收到信息时,她用她的私钥进行解密。当她决定回复信息时,她用David的公钥对她的信息进行加密,当David收到信息时,他用他的私钥对信息进行解密。
导入图书馆
//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();
我们已经为David和Viktoria生成了密钥。一对钥匙由公钥和私钥组成。这些钥匙的类型是 Uint8Array(32)
.
例如,David的密钥对将看起来像这样。
{
publicKey: Uint8Array(32) [
159, 32, 160, 185, 143, 29, 55, 23,
111, 203, 90, 224, 64, 90, 65, 75,
80, 149, 12, 124, 83, 145, 72, 162,
96, 163, 121, 157, 62, 78, 203, 52
],
secretKey: Uint8Array(32) [
72, 210, 106, 229, 196, 53, 2, 88,
124, 87, 128, 174, 185, 0, 192, 52,
5, 162, 11, 39, 23, 183, 103, 165,
40, 128, 179, 242, 38, 132, 78, 241
]
}
David正在加密信息
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;
};
-
我们将生成一个一次性代码,这个代码即只对当前进程有效。
-
我们将从David那里得到纯文本。
-
我们将使用
nacl.box()
,通过以下参数组成密码文本。-
通过
decodeUTF8()
,将明文作为参数传递,产生一串Unicode字符。 -
一次性代码。
-
Viktoria的公钥。
-
David的私钥。
-
按照库的规定,要发送给收件人的信息是。
-
密码文本。
-
一次性代码。
Viktoria解密该信息
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;
};
输出。
Hello there Viktoria
我们正在使用密码文本、一次性代码、David的公钥和Viktoria的秘钥对信息进行解码。然后使用encodeUTF8()
,将该信息编码为UTF8
,以便其可被人类阅读。
中间人攻击
在公钥密码学中,公钥被广泛传播。这意味着,攻击者可能会得到另一方的公钥。如果甲方与乙方进行通信,攻击者可以冒充自己,当甲方向乙方发送信息时,信息在到达乙方之前就已经到达攻击者手中。
然后,攻击者修改信息并将修改后的信息发送给乙方。当乙方决定回复时,信息再次被发送给攻击者,攻击者修改了信息并将修改后的信息发送给甲方。这是对公钥密码学的一个主要威胁。
使用预先计算的密钥
为了遏制上述威胁,我们使用预先计算的密钥。在这里,在加密和解密时,我们使用一个共享密钥,而不是使用可能被冒充的另一方的公钥。共享密钥是收件人的公钥和发件人的秘钥的一个特殊组合密钥。
David 加密信息
function davidEncrypting(){
//David computes a one time shared key
const david_shared_key = nacl.box.before(viktoria.publicKey,david.secretKey);
//David also computes a one time code.
const one_time_code = nacl.randomBytes(24);
//Davids message
const plain_text = "Hey!!, our communication is now more secure";
//Getting the cipher text
const cipher_text = nacl.box.after(
nacl.util.decodeUTF8(plain_text),
one_time_code,
david_shared_key
);
//message to be transited.
const message_in_transit = {cipher_text,one_time_code};
return message_in_transit;
};
-
我们将根据Viktoria的公钥和David的秘钥计算出一个共享密钥。
-
我们将生成一个一次性代码。
-
我们将从David那里得到纯文本。
-
我们将使用
nacl.box.after()
,通过以下参数计算出密码文本。-
通过将明文传给
decodeUTF8()
,生成一串Unicode字符。 -
一次性代码。
-
David的共享密钥。
-
将要发送给收件人的信息由以下部分组成。
-
密码文本。
-
一次性代码。
Viktoria对信息进行解密
function viktoriaDecrypting(message){
//Getting Viktoria's shared key
const viktoria_shared_key = nacl.box.before(david.publicKey,viktoria.secretKey);
//Get the decoded message
let decoded_message = nacl.box.open.after(message.cipher_text,message.one_time_code,viktoria_shared_key);
//Get the human readable message
let plain_text = nacl.util.encodeUTF8(decoded_message)
//return the message
return plain_text;
};
输出。
Hey!!, our communication is now more secure
-
我们将得到Viktoria的共享密钥。
-
我们将使用密码文本、一次性代码和她的共享密钥来解码Viktoria的信息。
-
我们将使用
encodeUTF8()
,将信息编码为UTF8
,使其可被人类阅读。
维护公钥
公钥基础设施是一个负责维护和注册公钥的机构。使用公钥基础设施的实际领域是银行。所有银行的钥匙都由一个机构存储和维护。因此,当一家银行想向另一家银行转移资金时,他们会从共同的机构获得钥匙。公钥基础设施确保了公钥的可信度,从而防止了中间人的攻击。
维护私人或秘密钥匙
维护这些钥匙是非常重要的,因为它们是至关重要的。目前,它们被在线存储在数据库或通过一些其他媒介。它们通常使用加密算法(如Advanced Encryption Standard (AES)
)进行加密,以便在存储之前促进其完整性。
采用公钥加密法的平台
一些在生产中使用公钥加密技术的平台包括。
- [Whatsapp]
- [Threema]
- [SSL/TLS握手]
结论
公钥加密法解决了密钥分配问题,但遭受到中间人攻击的威胁。有不同的方法来解决这个问题,其中包括使用预先计算的密钥。这种方法仍然有需求,并被许多成功的公司所使用。
在这篇文章中,我们已经介绍了公钥密码学,使用公钥密码学的算法,在JavaScript中实现公钥密码学时要使用的库。
我们还使用tweetnacl.js
实现了公钥密码学,我们讨论了中间人攻击,一个使用预先计算的密钥的简单例子,我们如何维护公钥和私钥,我们还提到了今天使用公钥密码学的平台。