Table of Contents

组件:数据卡

此组件由数据卡提供。

组件名:data

1级回调函数

2级回调函数

3级回调函数

样例

此扩展卡可用于向其他在游戏中或在现实中的人发送加密数据。既然我们有能力创建密钥对和Diffie-Hellman共享密钥,那么我们就可以与这些人建立加密连接。

使用密钥对进行加密时,基本步骤为:

预备工作:

发送者必须:

接收者必须:

注*:上文中使用了“加密密钥”和“解密密钥”两个术语。这两个密钥完全相同,因为这两个密钥都是使用ecdh()函数生成的。

注**:上文说“你需要将rPublic手动传给发送者”。但是在使用握手协议的系统中情况并非如此。例如,发送者会让接收者知道自己的存在,然后接收者会回复给发送者一个公钥(可能还有附加信息,例如密钥长度)。为简单起见,以下示例不涵盖握手协议的功能。

注***:上文与下文的示例提到需要将密钥和信息序列化/解序列化。总体来说,在你将数据(尤其是二进制形式的)写入文件或通过网络传输前对其序列化是有益的。序列化能保证二进制数据“有结尾”,使你的脚本或shell读取时更加安全。

若要发送加密数据:

snippet.lua
local serialization  = require("serialization")
local component      = require("component")
 
--此表包含了要发送到接收方电脑的数据。
--表中还有信息头,供接收方用来解密数据。
local __packet =
{
    header =
    {
        sPublic    = nil,
        iv         = nil
    },
 
    data = nil
}
 
--读取公钥文件。
local file = io.open("rPublic","rb")
 
local rPublic = file:read("*a")
 
file:close()
 
--将公钥解序列化为二进制形式。
local rPublic = serialization.unserialize(rPublic)
 
--重建公钥对象。
local rPublic = component.data.deserializeKey(rPublic,"ec-public")
 
--为此会话生成一个公钥与一个私钥。
local sPublic, sPrivate = component.data.generateKeyPair(384)
 
--生成一个加密密钥。
local encryptionKey = component.data.md5(component.data.ecdh(sPrivate, rPublic))
 
--将信息头中值'iv'设定为一个随机生成的16位数字字符串。
__packet.header.iv = component.data.random(16)
 
--将信息头中值'sPublic'设定为一个字符串。
__packet.header.sPublic = sPublic.serialize()
 
--待加密的数据。
__packet.data = "lorem ipsum"
 
--数据被序列化并被加密了。
__packet.data = component.data.encrypt(serialization.serialize(__packet.data), encryptionKey, __packet.header.iv)
 
--为简单起见,此样例中的电脑使用连接卡(ocdoc.cil.li/item:linked_card:zh)
component.tunnel.send(serialization.serialize(__packet))

若要接收加密数据:

snippet.lua
local serialization = require("serialization")
local component     = require("component")
local event         = require("event")
 
--读取私钥。
local file = io.open("rPrivate","rb")
 
local rPrivate = file:read("*a")
 
file:close()
 
--将私钥解序列化。
local rPrivate = serialization.unserialize(rPrivate)
 
--重建私钥对象。
local rPrivate = component.data.deserializeKey(rPrivate,"ec-private")
 
--使用event.pull()以接收来自发送者的信息。
local _, _, _, _, _, message = event.pull("modem_message")
 
--将信息解序列化。
local message = serialization.unserialize(message)
 
--从信息中获取公钥并解序列化。
local sPublic = component.data.deserializeKey(message.header.sPublic,"ec-public")
 
--生成解密密钥。
local decryptionKey = component.data.md5(component.data.ecdh(rPrivate, sPublic))
 
--使用解密密钥和IV来解密message.data中的加密数据
local data = component.data.decrypt(message.data, decryptionKey, message.header.iv)
 
--解序列化解密后的数据。
local data = serialization.unserialize(data)
 
--输出解密后的数据。
print(data)

目录