
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 19 KiB |
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.1 KiB |
Before Width: | Height: | Size: 78 KiB After Width: | Height: | Size: 78 KiB |
Before Width: | Height: | Size: 4.4 KiB After Width: | Height: | Size: 4.4 KiB |
Before Width: | Height: | Size: 6.1 KiB After Width: | Height: | Size: 6.1 KiB |
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 21 KiB |
Before Width: | Height: | Size: 79 KiB After Width: | Height: | Size: 79 KiB |
@ -1,3 +1,3 @@ |
|||
[submodule "docs/wiki"] |
|||
path = docs.old/wiki |
|||
path = .docs.old/wiki |
|||
url = https://github.com/DECODEproject/zenroom.wiki.git |
|||
|
@ -0,0 +1 @@ |
|||
This is a secret message. |
@ -0,0 +1,14 @@ |
|||
{ |
|||
"keyring" : { |
|||
"public" : "u64:BPx7noN1G4tbDBxE1CFxmOaFaIAY0tsh6nLjaKXo5XCm1cDmNyGk9uVav-ElwaqjlpGqjwXwaDnPELXm8PzD0UlXNFudDWc2Sz8xjJsdCQlvLfBc_p_WnvVO3NBNcA9Jr9bPK2_nFAtGs1GZ1Eig4TM", |
|||
"secret" : "u64:NQePSaOl3jd9YO4fCEAFm4mn_cn4Lnw4Qr4yZppNS-IVqSNp24hWEnyCyub4gldZ_Wt5AEmtRtU" |
|||
}, |
|||
"recipients" : { |
|||
"mayo" : "u64:BGzS9Zk38I73Dzix-gNILRWn1HXJAs56Yw86P_jNjLu6ocUQp1aO_g5dUsRNuryK6Jx3SplBLHy1bmH3XVhcVn6X63_FBCaRsTRJlILCTk-0y0dq6y8AJB6MxVR77dzoGyLkZH5Q1MQilZM7w3ltc54", |
|||
"jim" : "u64:BKJy7FOdD9e1fcbhp-7-KmveqMQ0jKAjj4Uzt9vWXxeEsyK29s0j5W3rygazdaVx8XG3ly8oxhqhNLjCelYVKSZRlt7Yt-MO8dk82Gg0SkneBSseZsfg3kmPGwRgE2kT4vSVRTI5EhQQFowvTv4av6E", |
|||
"jaromil" : "u64:BNvABN9bln4VVi4Mk1n68m91pfMyTLK_CokhVVKM8jjLFeWHjt5lCjr16o5OHKFdLidf0c5QDS_xz30ZP54BiGSdCSv1Mg1KJ8jpv2PRnr0LGHqdEjxUo2S5Il6t49JRXdSdT_dT1G--ro8X9Yuha2Q", |
|||
"paulus" : "u64:BACm5xAfJzjwAYup3P4lcNLNAmsx8-hHUMPOqNJJUkE7mbmeCxP4TeScv047LlGKxKOwKBZUhSEOYpPxWWTqIRv9bHq-vlrEL-IG1mrJ33OneI9m4Gz84ie5QpHMh9RWQ5MCguo6J4SEUWY42UUOvEM", |
|||
"francesca" : "u64:BOxh59-_IuE2EJ0Ph4wSSUUCSQ84OzodsE2tOPgXSMS0uMu7KpKbFhoWvwl141Vrs0NslqqwBMmgcwaHS2IsMt96sOUr3MApn7bYNd4xUw7OzHOO9wrtY4-ws8rvpPzeQIxDAVnr7Z2eDhXQrUQXcbk", |
|||
"mark" : "u64:BKR0eWc0av_etfqgE1ZoYKTJQGHdI3Mvp_zInb7MSuJUSV4vEaKAMV4Uem21Azy7aaIO-lU5lbxcUqJfhzhKzKQDgRPwlNtqVRVzzl0EzXkt1xN1jjsicaVV1t8HWO3O_SKDGL-OEmf9QRQg78FBLbQ" |
|||
} |
|||
} |
@ -0,0 +1,36 @@ |
|||
-- encrypt a secret to multiple recipients |
|||
|
|||
-- run with arguments: |
|||
-- -a crypto-to-multi.data -k crypt-to-multi.keys |
|||
|
|||
-- inside KEYS is a list of names and public keys encoded with b58; it |
|||
-- returns a list of recipients and encrypted secrets for each and the |
|||
-- sender's public key |
|||
|
|||
secret = str(DATA) |
|||
|
|||
keys = JSON.decode(KEYS) |
|||
|
|||
-- this is our own secret key, combined with the recipient's public |
|||
-- key to obtain a session key |
|||
local private = url64(keys.keyring.secret) |
|||
res = {} |
|||
|
|||
-- loop through all recipients |
|||
for name,pubkey in pairs(keys.recipients) do |
|||
-- calculate the session key |
|||
|
|||
session = ECDH.session(private, url64(pubkey)) |
|||
iv = O.random(32) |
|||
|
|||
out = { header = "encoded using zenroom " .. VERSION.original} |
|||
-- encrypt the message with the session key |
|||
out.text, out.checksum = |
|||
ECDH.aead_encrypt(KDF(session), secret, iv, out.header) |
|||
|
|||
-- insert results in final json array |
|||
res[name] = url64( JSON.encode(out) ) |
|||
end |
|||
|
|||
-- return the json array |
|||
print(JSON.encode(res)) |
@ -0,0 +1,5 @@ |
|||
{ |
|||
"checksum" : "u64:3wPJiE4ZzZEHprA4Lsr-TQ", |
|||
"text" : "u64:7xKuOiQ5oZxz0KtS1Yku-XKdsAQc-YPq0EW1FJhjLCzyGruMwC4PUuenUpG1U4AxFTaB06UpoXIBwCMm80XXgu4", |
|||
"header" : "u64:eyJpdiI6InU2NDpPOFBMYzBfdTRsdmpFQkQwMlZsN2I0Mng1Y3FwUWlJdUcwQ1Nfd2lsQmFRIiwiZGV2aWNlX3B1YmtleSI6InU2NDpCTkRLRm5OVThzM05fWFoySmlVazlIOVg5VU1MRm5sMUp1TDl1SEs0SmdrVTFPQUFMMko4ZFZLR3RWaXFFY3Nfd0wwQ0JpdHhXVG80ZUIyMlJNWTAxN29udE9vVlF4TVNyZllhVmhZT2FJV0NaZTYwZXM4SjhSb1JJT285ZHFqTWY0d0F2VG9mMzRzbFZLek85VURLOEc4IiwiY29tbXVuaXR5X2lkIjoic21hcnRjaXRpemVucyJ9" |
|||
} |
@ -0,0 +1,3 @@ |
|||
{ |
|||
"community_seckey": "u64:Cf88o0bEY3igf3mbnKTT7s7_huXDPvlATz7J1T7atZo" |
|||
} |
@ -0,0 +1,17 @@ |
|||
-- a dashboard receives an ID and payload packet from an IoT device |
|||
|
|||
-- read and validate data |
|||
keys = I.spy( JSON.decode(KEYS) ) |
|||
data = I.spy( JSON.decode(DATA) ) |
|||
|
|||
decode = { header = JSON.decode(url64(data.header)) } |
|||
|
|||
commsec = url64(keys.community_seckey) |
|||
devpub = url64(decode.header.device_pubkey) |
|||
session = ECDH.session(commsec, devpub) |
|||
decode.text, decode.checksum = |
|||
ECDH.aead_decrypt(KDF(session), url64(data.text), url64(decode.header.iv), data.header) |
|||
|
|||
assert(decode.checksum == url64(data.checksum)) |
|||
print(JSON.encode(decode)) |
|||
|
@ -0,0 +1,15 @@ |
|||
hello = str("Hello World!") |
|||
print(hello:string()) |
|||
print("in hex: " .. hello:hex()) |
|||
print("in base64: " .. hello:base64()) |
|||
|
|||
hello = hex("48656c6c6f20576f726c6421") |
|||
print("re-assign from hex, length "..#hello) |
|||
print("as string: " .. hello:string()) |
|||
print("in base64: " .. hello:base64()) |
|||
|
|||
hello = base64("b64:SGVsbG8gV29ybGQh") |
|||
print("re-assign from base64, length "..#hello) |
|||
print("as string: " .. hello:string()) |
|||
print("in hex: " .. hello:hex()) |
|||
|
@ -0,0 +1,70 @@ |
|||
-- ECQV (Qu-Vanstone Implicit Certificate Scheme) |
|||
-- Zenroom implementation by Jaromil |
|||
-- based on "Standards for Efficient Cryptogrpahy" |
|||
-- specification SEC 4 v1.0 retrieved from www.secg.org |
|||
|
|||
-- setup |
|||
ECP = require_once'zenroom_ecp' |
|||
G = ECP.generator() |
|||
|
|||
-- typical EC key generation on G1 |
|||
-- take a random big integer modulo curve order |
|||
-- and multiply it by the curve generator |
|||
|
|||
function keygen() |
|||
local key = INT.random() |
|||
return { private = key, |
|||
public = key * G } |
|||
end |
|||
|
|||
-- generate the certification request |
|||
certreq = keygen() |
|||
-- certreq.private is preserved in a safe place |
|||
-- certreq.public is sent to the CA along with a declaration |
|||
declaration = { requester = "Alice", |
|||
statement = "I am stuck in Wonderland" } |
|||
print("Declaration:") |
|||
I.print(declaration) |
|||
-- Requester sends to CA --> |
|||
|
|||
-- ... once upon a time ... |
|||
|
|||
-- --> CA receives from Requester |
|||
-- keypair for CA (known to everyone as the Mad Hatter) |
|||
CA = keygen() |
|||
|
|||
-- from here the CA has received the request |
|||
certkey = keygen() |
|||
-- certkey.private is sent to requester |
|||
-- certkey.public is broadcasted |
|||
|
|||
-- public key reconstruction data |
|||
certpub = certreq.public + certkey.public |
|||
-- the certification is serialized (could use ASN-1 or X509) |
|||
certification = { public = certpub, |
|||
requester = declaration.requester, |
|||
statement = declaration.statement, |
|||
certifier = str("Mad Hatter") } |
|||
CERT = sha256(OCTET.serialize(certification)) |
|||
CERThash = INT.new(CERT) |
|||
-- private key reconstruction data |
|||
certpriv = (CERThash * certkey.private + CA.private) |
|||
-- CA sends to Requester certpriv and CERThash |
|||
-- eventually CA broadcasts certpub and CERThash |
|||
|
|||
-- ... on the other side of the mirror ... |
|||
|
|||
-- Alice has received from the CA the certpriv and CERT |
|||
-- which can be used to create a new CERTprivate key |
|||
CERTprivate = (CERThash * certreq.private + certpriv) % ECP.order() |
|||
|
|||
-- Anyone may receive the certpub and CERThash and, knowing the CA |
|||
-- public key, can recover the same CERTpublic key from them |
|||
CERTpublic = certpub * CERThash + CA.public |
|||
|
|||
-- As a proof here we generate the public key in a standard way, |
|||
-- multiplying it by the curve generator point, then check equality |
|||
assert(CERTpublic == G * CERTprivate) |
|||
print "Certification by Mad Hatter:" |
|||
I.print({ private = CERTprivate:octet():hex(), |
|||
public = CERTpublic:octet():hex() }) |
@ -0,0 +1 @@ |
|||
Some, sort, of, sensor, data |
@ -0,0 +1,6 @@ |
|||
{ |
|||
"device_id": "anonymous", |
|||
"community_id": "smartcitizens", |
|||
"community_pubkey": "u64:BCfdjzF7npsNdTNlvUA62TOlwdTHi8e_28gPGsUcVHYYaiRIaOcl8_51IAwB7xaSlPvNZBLK5THb9S6jkmt7z9oHcwUcrB7xvuwj7YKIWZDOB-1r8pzH7YCaTQmSWkxrr_FfboSq1rfHx_7ZeHgjS-I" |
|||
} |
|||
|
@ -0,0 +1,41 @@ |
|||
-- one iot device encrypts its data and ID to a community dashboard |
|||
-- defines data validation shcemas that can be used on both ends |
|||
-- complementary to other script for reception |
|||
|
|||
-- import and validate keys |
|||
keys = JSON.decode(KEYS) |
|||
|
|||
-- generate a new device keypair every time |
|||
-- this could be optimised by creating keys onetime at first run |
|||
-- or temporarily, i.e: every day or every hour |
|||
devkey = ECDH.keygen() |
|||
|
|||
-- compute the session key using private/public keys |
|||
-- it may change to use random, but then we need a session channel |
|||
|
|||
-- payload is a nested json structure to be encrypted |
|||
payload = {} |
|||
payload.device_id = keys.device_id |
|||
payload.data = DATA |
|||
|
|||
-- The device's public key, the 'community_id' and the encryption |
|||
-- curve type are transmitted in clear inside the header, which is |
|||
-- authenticated (AEAD) |
|||
header = {} |
|||
header.device_pubkey = devkey.public:url64() |
|||
header.community_id = keys.community_id |
|||
header.iv = O.random(32):url64() |
|||
|
|||
-- content( header ) -- uncomment for debug |
|||
|
|||
-- The output is a table with crypto contents which is standard for |
|||
-- zenroom's functions encrypt/decrypt: .checksum .header .iv .text |
|||
local session = ECDH.session(devkey.private, url64(keys.community_pubkey)) |
|||
local out = { header = url64(JSON.encode(header)) } |
|||
out.text, out.checksum = |
|||
ECDH.aead_encrypt(KDF(session), JSON.encode(payload), header.iv, out.header) |
|||
|
|||
-- content(output) -- uncomment for debug |
|||
print( JSON.encode( out ) ) -- map(output, url64) ) ) |
|||
|
|||
|
@ -0,0 +1,36 @@ |
|||
{ |
|||
"squadName": "Super hero squad", |
|||
"homeTown": "Metro City", |
|||
"formed": 2016, |
|||
"secretBase": "Super tower", |
|||
"active": true, |
|||
"Molecule Man": { |
|||
"age": 29, |
|||
"secretIdentity": "Dan Jukes", |
|||
"powers": [ |
|||
"Radiation resistance", |
|||
"Turning tiny", |
|||
"Radiation blast" |
|||
] |
|||
}, |
|||
"Madame Uppercut": { |
|||
"age": 39, |
|||
"secretIdentity": "Jane Wilson", |
|||
"powers": [ |
|||
"Million tonne punch", |
|||
"Damage resistance", |
|||
"Superhuman reflexes" |
|||
] |
|||
}, |
|||
"Eternal Flame": { |
|||
"age": 1000000, |
|||
"secretIdentity": "Unknown", |
|||
"powers": [ |
|||
"Immortality", |
|||
"Heat Immunity", |
|||
"Inferno", |
|||
"Teleportation", |
|||
"Interdimensional travel" |
|||
] |
|||
} |
|||
} |
@ -0,0 +1,19 @@ |
|||
-- Example demonstrating how to manipulate complex data structures |
|||
-- (called tables) and convert them back and forth to JSON strings |
|||
|
|||
-- using the "inspection module" to print contents of complex data |
|||
-- structures: inside.print() instead of print() |
|||
|
|||
-- this converts the JSON string to a table on which various |
|||
-- operations can be done (see @tables and @functions modules) |
|||
superheroes = JSON.decode(DATA) |
|||
|
|||
-- iterate through the members array and print |
|||
-- out only names. ipairs is very unelegand |
|||
print "import from JSON" |
|||
I.print(superheroes) |
|||
|
|||
print "flatten tree" |
|||
superflat = flatten(superheroes) |
|||
I.print(superflat) |
|||
|
@ -0,0 +1,23 @@ |
|||
-- generate a private keyring and other fictional public keys |
|||
|
|||
-- run with: zenroom keygen.zen |
|||
|
|||
-- any combination of public and private keys generated this way and |
|||
-- exchanged among different people will lead to the same secret which |
|||
-- is then usable for asymmetric encryption. |
|||
|
|||
recipients={'jaromil','francesca','jim','mark','paulus','mayo'} |
|||
keys={} |
|||
for i,name in ipairs(recipients) do |
|||
kk = ECDH.keygen() |
|||
keys[name] = kk.public:url64() |
|||
end |
|||
|
|||
|
|||
keyring = ECDH.keygen() |
|||
|
|||
keypairs = JSON.encode({ |
|||
keyring={public=keyring.public:url64(), |
|||
secret=keyring.private:url64()}, |
|||
recipients=keys}) |
|||
print(keypairs) |
@ -0,0 +1,12 @@ |
|||
-- generate a simple keyring |
|||
keyring = ECDH.new() |
|||
keyring:keygen() |
|||
|
|||
-- export the keypair to json |
|||
export = JSON.encode( |
|||
{ |
|||
public = keyring: public():url64(), |
|||
private = keyring:private():url64() |
|||
} |
|||
) |
|||
print(export) |
@ -0,0 +1,6 @@ |
|||
{ |
|||
"pin": "1234", |
|||
"text": "my private declaration or certificate of sorts", |
|||
"salt": "c6e49670a3c65d7f19ee7d39a25478900f8e98ec1e9a82131e23e7b07d17c0c9", |
|||
"iterations": 10000 |
|||
} |