**This is an old revision of the document!**

组件:数据卡

此组件由数据卡提供。

组件名:data

1级回调函数

  • crc32(data:string):string
    计算数据的CRC-32哈希值。结果为二进制格式。
  • decode64(data:string):string
    对数据进行base64解码。
  • encode64(data:string):string
    对数据进行base64编码。结果为二进制格式。
  • md5(data:string):string
    计算数据的MD5哈希值。结果为二进制格式。
  • sha256(data:string):string
    计算数据的SHA2-256哈希值。结果为二进制格式。
  • deflate(data:string):string
    对数据用deflate算法压缩。
  • inflate(data:string):string
    对数据用infalte算法解压。
  • getLimit():number
    返回单次可被传递给此扩展卡其他函数的最大数据大小。

2级回调函数

  • encrypt(data:string, key:string, iv:string):string
    使用给定密钥以及初始向量IV(最好为随机)对数据进行AES加密。
  • decrypt(data:string, key:string, iv:string):string
    使用给定密钥以及初始向量IV对数据进行AES解密。
  • random(len:number):string
    生成长度为 len 的随机二进制字符串。

3级回调函数

  • generateKeyPair([bitLen:number]):table, table
    生成一对可用于多种加密算法的公钥与私钥。可选的第二个参数代表密钥长度,值可为256或384。
    密钥类型包括“ec-public”和“ec-private”。密钥可以使用key.serialize():string来序列化。密钥中还包含一个函数key.isPublic():boolean
  • ecdsa(data:string, key:userdata[, sig:string]):string or boolean
    不给定签名则使用给定私钥生成数据的一份签名。若给定了签名则功能为使用公钥、先前生成的签名字符串以及原字符串验证签名。
  • ecdh(privateKey:userdata, publicKey:userdata):string
    使用第一个参数给出的用户私钥与第二个参数给出的用户公钥,生成一个Diffie-Hellman共享密钥。密钥基本关系的样例为: ecdh(userA.private, userB.public) == ecdh(userB.private, userA.public)
  • deserializeKey(data:string, type:string):table
    将密钥从字符串形式转化为其特有形式。

Examples

This card can be used to transmit encrypted data to other in-game or real-life peers. Since we are given the ability to create key-pairs and Diffie-Hellman shared keys, we are able to establish encrypted connections with these peers.

When using key pairs for encryption, the basic concept is this

Preliminary Setup:

  • (The following items are to be done on the RECEIVER)
  • Generate a public key (rPublic) and private key (rPrivate).
  • **If no automated key exchange, then you'll need to send rPublic to the SENDER manually.

The SENDER must:

  • ***Read the RECEIVER's public key (rPublic), unserialize it, and rebuild the key object.
  • Generate a public key (sPublic) and private key (sPrivate).
  • *Generate an encryption key using rPublic and sPrivate.
  • Generate an Initialization Vector (IV).
  • Convert sPublic into a string with sPublic.serialize().
  • ***Serialize the data using the serialization library, then encrypt it using the encryption key and IV.
  • Serialize and transmit the message, with sPublic and IV in plain-text.

The RECEIVER must:

  • Read the RECEIVER's private key (rPrivate), unserialize it, and rebuild the key object.
  • Receive the message and unserialize it using the serialization library, then deserialize sPublic using data.deserializeKey().
  • *Generate a decryption key using sPublic and rPrivate.
  • Use the decryption key, along with the IV, to decrypt the message.
  • Unserialize the decrypted data.

NOTE* In the above, the terms 'encryption key' and 'decryption key' are used. These keys are, byte-for-byte, the same. This is because both keys were generated using the ecdh() function.

NOTE** In the above, it is stated that you will manually transfer rPublic to SENDER. This would not be the case in systems that employ a handshake protocol. For example, SENDER would make themselves known to RECEIVER, who will then reply to SENDER with a public key (and possibly additional information, such as key-length). For simplicity, the following examples will not cover the functions of handshake protocols.

NOTE*** The examples above and below state that you must serialize/unserialize a key or message. In-general, it is good practice to serialize data (especially when in binary format) before you write it to a file, or transfer it on the network. Serialization makes sure that the binary data is 'escaped', making it safe for your script or shell to read.

To send an encrypted message:

snippet.lua
local serialization  = require("serialization")
local component      = require("component")
 
-- This table contains the data that will be sent to the receiving computer.
-- Along with header information the receiver will use to decrypt the message.
local __packet =
{
    header =
    {
        sPublic    = nil,
        iv         = nil
    },
 
    data = nil
}
 
-- Read the public key file.
local file = io.open("rPublic","rb")
 
local rPublic = file:read("*a")
 
file:close()
 
-- Unserialize the public key into binary form.
local rPublic = serialization.unserialize(rPublic)
 
-- Rebuild the public key object.
local rPublic = component.data.deserializeKey(rPublic,"ec-public")
 
-- Generate a public and private keypair for this session.
local sPublic, sPrivate = component.data.generateKeyPair(384)
 
-- Generate an encryption key.
local encryptionKey = component.data.md5(component.data.ecdh(sPrivate, rPublic))
 
-- Set the header value 'iv' to a randomly generated 16 digit string.
__packet.header.iv = component.data.random(16)
 
-- Set the header value 'sPublic' to a string.
__packet.header.sPublic = sPublic.serialize()
 
-- The data that is to be encrypted.
__packet.data = "lorem ipsum"
 
-- Data is serialized and encrypted.
__packet.data = component.data.encrypt(serialization.serialize(__packet.data), encryptionKey, __packet.header.iv)
 
-- For simplicity, in this example the computers are using a Linked Card (ocdoc.cil.li/item:linked_card)
component.tunnel.send(serialization.serialize(__packet))

To receive the encrypted message:

snippet.lua
local serialization = require("serialization")
local component     = require("component")
local event         = require("event")
 
-- Read the private key
local file = io.open("rPrivate","rb")
 
local rPrivate = file:read("*a")
 
file:close()
 
-- Unserialize the private key
local rPrivate = serialization.unserialize(rPrivate)
 
-- Rebuild the private key object
local rPrivate = component.data.deserializeKey(rPrivate,"ec-private")
 
-- Use event.pull() to receive the message from SENDER.
local _, _, _, _, _, message = event.pull("modem_message")
 
-- Unserialize the message
local message = serialization.unserialize(message)
 
-- From the message, deserialize the public key.
local sPublic = component.data.deserializeKey(message.header.sPublic,"ec-public")
 
-- Generate the decryption key.
local decryptionKey = component.data.md5(component.data.ecdh(rPrivate, sPublic))
 
-- Use the decryption key and the IV to decrypt the encrypted data in message.data
local data = component.data.decrypt(message.data, decryptionKey, message.header.iv)
 
-- Unserialize the decrypted data.
local data = serialization.unserialize(data)
 
-- Print the decrypted data.
print(data)

目录