Data Card: Difference between revisions

From OpenComputers: Rebooted
Jump to navigation Jump to search
imported>OCDoc Import
Imported from legacy OpenComputers documentation at ocdoc.cil.li
 
Unify block and component API pages
Line 1: Line 1:
= Data Card =
= Overview =


'''Provides''': [[Component/data|Data Card]] component.
The data card provides a variety of data encoding and decoding functionality, hashing, encryption and decryption, etc. There is a limit to the size of data that can be passed into any function provided by the data component. The higher the tier of data card, the more functionality is available. Usage can be found in the [[#Component API|component API]] section.


The data card provides a variety of data encoding and decoding functionality, hashing, encryption and decryption, etc. There is a limit to the size of data that can be passed into any function provided by the data component. The higher the tier of data card, the more functionality is available. Usage can be found on the [[Component/data|data]] component page.
= Crafting =
 
= ==== Crafting =


The Data card (tier 1) is crafted using the following recipe:
The Data card (tier 1) is crafted using the following recipe:
Line 34: Line 32:
[[File:t3datacard.png|200px]]
[[File:t3datacard.png|200px]]


Component name: <code>data</code>.
= Tier 1 API =
{{APICallback|name=crc32|signature=(data:string):string|description=
Computes CRC-32 hash of the data. Result is in binary format.
}}
{{APICallback|name=decode64|signature=(data:string):string|description=
Applies base64 decoding to the data.
}}
{{APICallback|name=encode64|signature=(data:string):string|description=
Applies base64 encoding to the data. Result is in binary format.
}}
{{APICallback|name=md5|signature=(data:string):string|description=
Computes MD5 hash of the data. Result is in binary format
}}
{{APICallback|name=sha256|signature=(data:string):string|description=
Computes SHA2-256 hash of the data. Result is in binary format.
}}
{{APICallback|name=deflate|signature=(data:string):string|description=
Applies deflate compression to the data.
}}
{{APICallback|name=inflate|signature=(data:string):string|description=
Applies inflate decompression to the data.
}}
{{APICallback|name=getLimit|signature=():number|description=
The maximum size of data that can be passed to other functions of the card.
}}
= Tier 2 API =
{{APICallback|name=encrypt|signature=(data:string, key:string, iv:string):string|description=
Applies AES encryption to the data using the key and (preferably) random IV.
}}
{{APICallback|name=decrypt|signature=(data:string, key:string, iv:string):string|description=
Reverses AES encryption on the data using the key and the IV.
}}
{{APICallback|name=random|signature=(len:number):string|description=
Generates a random binary string of len length.
}}
= Tier 3 API =
{{APICallback|name=generateKeyPair|signature=([bitLen:number]):table, table|description=
Generates a public/private key pair for various cryptiographic functions.
Optional second parameter specifies key length, 256 or 384 bits accepted.
Key types include "ec-public" and "ec-private". Keys can be serialized with
key.serialize():string Keys also contain the function key.isPublic():boolean
}}
{{APICallback|name=ecdsa|signature=(data:string, key:userdata[, sig:string]):string or boolean|description=
Generates a signiture of data using a private key. If signature is present
verifies the signature using the public key, the previously generated
signature string and the original string.
}}
{{APICallback|name=ecdh|signature=(privateKey:userdata, publicKey:userdata):string|description=
Generates a Diffie-Hellman shared key using the first user's private key and
the second user's public key. An example of a basic key relation:
<code>ecdh(userA.private, userB.public) == ecdh(userB.private, userA.public)</code>
}}
{{APICallback|name=deserializeKey|signature=(data:string, type:string):table|description=
Transforms a key from string to it's arbitrary type.
}}
= 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 <code>ecdh()</code> 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:
<syntaxhighlight lang="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))
</syntaxhighlight>
To receive the encrypted message: <syntaxhighlight lang="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)
</syntaxhighlight>
{{:Contents}}

Revision as of 19:56, 28 August 2026

Overview

The data card provides a variety of data encoding and decoding functionality, hashing, encryption and decryption, etc. There is a limit to the size of data that can be passed into any function provided by the data component. The higher the tier of data card, the more functionality is available. Usage can be found in the component API section.

Crafting

The Data card (tier 1) is crafted using the following recipe:

The Data card (tier 2) is crafted using the following recipe:

The Data card (tier 3) is crafted using the following recipe:

Component name: data.

Tier 1 API

crc32

crc32(data:string):string

Computes CRC-32 hash of the data. Result is in binary format.

decode64

decode64(data:string):string

Applies base64 decoding to the data.

encode64

encode64(data:string):string

Applies base64 encoding to the data. Result is in binary format.

md5

md5(data:string):string

Computes MD5 hash of the data. Result is in binary format

sha256

sha256(data:string):string

Computes SHA2-256 hash of the data. Result is in binary format.

deflate

deflate(data:string):string

Applies deflate compression to the data.

inflate

inflate(data:string):string

Applies inflate decompression to the data.

getLimit

getLimit():number

The maximum size of data that can be passed to other functions of the card.

Tier 2 API

encrypt

encrypt(data:string, key:string, iv:string):string

Applies AES encryption to the data using the key and (preferably) random IV.

decrypt

decrypt(data:string, key:string, iv:string):string

Reverses AES encryption on the data using the key and the IV.

random

random(len:number):string

Generates a random binary string of len length.

Tier 3 API

generateKeyPair

generateKeyPair([bitLen:number]):table, table

Generates a public/private key pair for various cryptiographic functions. Optional second parameter specifies key length, 256 or 384 bits accepted. Key types include "ec-public" and "ec-private". Keys can be serialized with key.serialize():string Keys also contain the function key.isPublic():boolean

ecdsa

ecdsa(data:string, key:userdata[, sig:string]):string or boolean

Generates a signiture of data using a private key. If signature is present verifies the signature using the public key, the previously generated signature string and the original string.

ecdh

ecdh(privateKey:userdata, publicKey:userdata):string

Generates a Diffie-Hellman shared key using the first user's private key and the second user's public key. An example of a basic key relation: ecdh(userA.private, userB.public) == ecdh(userB.private, userA.public)

deserializeKey

deserializeKey(data:string, type:string):table

Transforms a key from string to it's arbitrary type.

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:

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:

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)

We are currently in the process of unifying the separate block/item pages and component API pages together for ease of navigation. If you find the dedicated component API page is missing, check the item page. Thank you for your patience during this transition.


Links
OpenComputers
General Install and Use OpenOS - Crossmod Interoperation - Lua Conventions - Computer Users
Blocks
Computers Computer Case - Server Rack - Microcontrollers
Display Hologram Projector - Keyboard - Screen
Power and Networking Capacitor - Net Splitter - Power Converter - Power Distributor - Relay
Extensions Adapter - Cable - Disassembler - Disk Drive - Geolyzer - Motion Sensor - Redstone I/O - Transposer - 3D Printer
Robotics Assembler - Charger - Drone - Robot - Waypoint
Items
Components Data Card - Debug Card - Graphics Card - Internet Card - Linked Card - Network Card - Redstone Card - Wireless Network Card
Storage Devices Floppy Disk - EEPROM - Hard Disk Drive - Memory
Upgrades Angel Upgrade - Battery Upgrade - Chunkloader Upgrade - Database Upgrade - Experience Upgrade - Generator Upgrade - Hover Upgrade - Inventory Controller Upgrade - Inventory Upgrade - Leash Upgrade - Navigation Upgrade - Piston Upgrade - Sign I/O Upgrade - Solar Generator Upgrade - Tank Upgrade - Tank Controller Upgrade - Tractor Beam Upgrade - World Sensor Upgrade
Containers Card Container - Upgrade Container - Disk Drive
Others Analyzer - Texture Picker - Component Bus - CPU - APU - Drone Case - Manual - Microcontroller Case - Nanomachines - Remote Terminal - Terminal Server - Server - Tablet Case - Tablet - Crafting Materials - Ink Cartridge - Scrench - Hover Boots - Grog - Loot Disks
APIs
OpenOS buffer - colors - component - computer - event - filesystem - uuid - internet - keyboard - note - process - rc - robot - serialization - shell - sides - term - text - thread - transforms - unicode
Lua Libraries coroutine - package - io - os
Components
Core Components Abstract Bus - Access Point - Computer - Debug - Drone - Drive - EEPROM - Experience - Filesystem - Generator - GPU - Inventory Controller - Leash - Microcontroller - Modem - Navigation - Piston - Redstone - Robot - Sign - Tank Controller - Tractor Beam - Transposer - Tunnel - World Sensor
Others Component Access - Signals
Cross-Mod Integration Applied Energistics
Addon Mods
Addons Computronics
Supporting OpenComputers Thut's Concrete - HBM's Nuclear Tech Mod
Tutorials
Mod Specific Basic Computer - Writing Code - Hard Drives - Autorun and Startup scripts
Modding Custom Architectures - IMC Messages
Programs OPPM - install
Others Custom Operating Systems
Other Languages Page
Simplified Chinese 简体中文(Simplified Chinese)