此组件由数据卡提供。
组件名:data
。
crc32(data:string):string
decode64(data:string):string
encode64(data:string):string
md5(data:string):string
sha256(data:string):string
deflate(data:string):string
inflate(data:string):string
getLimit():number
encrypt(data:string, key:string, iv:string):string
decrypt(data:string, key:string, iv:string):string
random(len:number):string
len
的随机二进制字符串。generateKeyPair([bitLen:number]):table, table
key.serialize():string
来序列化。密钥中还包含一个函数key.isPublic():boolean
。ecdsa(data:string, key:userdata[, sig:string]):string or boolean
ecdh(privateKey:userdata, publicKey:userdata):string
ecdh(userA.private, userB.public) == ecdh(userB.private, userA.public)
deserializeKey(data:string, type:string):table
此扩展卡可用于向其他在游戏中或在现实中的人发送加密数据。既然我们有能力创建密钥对和Diffie-Hellman共享密钥,那么我们就可以与这些人建立加密连接。
使用密钥对进行加密时,基本步骤为:
预备工作:
rPublic
)与一个私钥(rPrivate
)。rPublic
手动传给发送者。发送者必须:
rPublic
),将其解序列化并重构出密钥对象。sPublic
)和一个私钥(sPrivate
)。rPublic
和sPrivate
生成加密密钥。sPublic.serialize()
将sPublic
转化为字符串sPublic
与IV。接收者必须:
rPrivate
),将其解序列化并重构出密钥对象。data.deserializeKey()
解序列化sPublic
。sPublic
和rPrivate
生成解密密钥。
注*:上文中使用了“加密密钥”和“解密密钥”两个术语。这两个密钥完全相同,因为这两个密钥都是使用ecdh()
函数生成的。
注**:上文说“你需要将rPublic
手动传给发送者”。但是在使用握手协议的系统中情况并非如此。例如,发送者会让接收者知道自己的存在,然后接收者会回复给发送者一个公钥(可能还有附加信息,例如密钥长度)。为简单起见,以下示例不涵盖握手协议的功能。
注***:上文与下文的示例提到需要将密钥和信息序列化/解序列化。总体来说,在你将数据(尤其是二进制形式的)写入文件或通过网络传输前对其序列化是有益的。序列化能保证二进制数据“有结尾”,使你的脚本或shell读取时更加安全。
若要发送加密数据:
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))
若要接收加密数据:
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)