Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CIP-0083 | Adding encrypted messages to CIP-0020 #409

Merged
merged 31 commits into from
Jan 17, 2023
Merged
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
2eb6a6e
Create README.md
gitmachtl Dec 8, 2022
c026721
Create democode-NODEJS.js
gitmachtl Dec 8, 2022
a029512
Create democode-PHP.php
gitmachtl Dec 8, 2022
1173c7f
Create democode-BASH.sh
gitmachtl Dec 8, 2022
269eb3f
Create normal-message-metadata.json
gitmachtl Dec 8, 2022
6fe29ee
Create encrypted-message-metadata.json
gitmachtl Dec 8, 2022
fb3dd6c
Removed markdown in the header preamble
gitmachtl Dec 8, 2022
d9008a1
Update README.md
gitmachtl Dec 8, 2022
11ce1a6
grammer correction
gitmachtl Dec 8, 2022
480cc9b
grammer correction
gitmachtl Dec 8, 2022
689c8b7
Create democode-WEB.js
gitmachtl Dec 8, 2022
5ca41b9
Added 'Path to Active' section
gitmachtl Dec 8, 2022
4449abd
Update AdaStat.net Screenshots
gitmachtl Dec 8, 2022
e364419
Update README.md
gitmachtl Dec 8, 2022
5ccfe89
Adding Eternl.io - Now active implementation
gitmachtl Jan 1, 2023
495cba1
removed '&nbsp;<p>'
gitmachtl Jan 17, 2023
35ba2f0
Updating formatting
gitmachtl Jan 17, 2023
d8b4249
moved integration examples into section 'path to active'
gitmachtl Jan 17, 2023
8512e5b
added comment about future mixed style option
gitmachtl Jan 17, 2023
b815244
added comment why base64 format was choosen
gitmachtl Jan 17, 2023
56099d2
Create format.cddl
gitmachtl Jan 17, 2023
9446227
Update README.md
gitmachtl Jan 17, 2023
66d451c
Changed status to 'Active'
gitmachtl Jan 17, 2023
51bbcd1
Update and rename CIP-????/README.md to CIP-0083/README.md
gitmachtl Jan 17, 2023
be17883
Rename CIP-????/format.cddl to CIP-0083/format.cddl
gitmachtl Jan 17, 2023
5b6a58a
Rename CIP-????/codesamples/democode-BASH.sh to CIP-0083/codesamples/…
gitmachtl Jan 17, 2023
261141b
Rename CIP-????/codesamples/democode-NODEJS.js to CIP-0083/codesample…
gitmachtl Jan 17, 2023
9924681
Rename CIP-????/codesamples/democode-PHP.php to CIP-0083/codesamples/…
gitmachtl Jan 17, 2023
97ec8b9
Rename CIP-????/codesamples/democode-WEB.js to CIP-0083/codesamples/d…
gitmachtl Jan 17, 2023
b4b2fa7
Rename CIP-????/codesamples/encrypted-message-metadata.json to CIP-00…
gitmachtl Jan 17, 2023
f96a00b
Rename CIP-????/codesamples/normal-message-metadata.json to CIP-0083/…
gitmachtl Jan 17, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
275 changes: 275 additions & 0 deletions CIP-????/README.md

Large diffs are not rendered by default.

50 changes: 50 additions & 0 deletions CIP-????/codesamples/democode-BASH.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
#!/bin/bash

# --------------------------------------------------------------------------------------------
# Demonstration implementation of CIP-0020 Transaction Messages Encryption/Decryption via BASH
# --------------------------------------------------------------------------------------------

#Setting default passphrase
passphrase="cardano"


#Unencrypted Metadata JSON
echo "Normal unencrpted messages metadata JSON:"
cat normal-message-metadata.json | jq
echo


#Encrypt the msg array from the JSON
encrText=$(jq -crM .\"674\".msg normal-message-metadata.json | openssl enc -e -aes-256-cbc -pbkdf2 -iter 10000 -a -k "${passphrase}")
echo "Encrypted Strings (base64 format):"
echo "${encrText}"
echo


#Compose it into a new JSON and add the 'enc' entry
echo "New encrypted messages metadata JSON:"
jq ".\"674\".msg = [ $(awk {'print "\""$1"\","'} <<< ${encrText} | sed '$ s/.$//') ]" <<< '{"674":{"enc":"basic"}}' | jq


echo
echo "----------------------"
echo


#Encrypted Metadata JSON
echo "Encrypted messages metadata JSON:"
cat encrypted-message-metadata.json | jq
echo


#Decrypt the msg array from the JSON
decrText=$(jq -crM ".\"674\".msg[]" encrypted-message-metadata.json | openssl enc -d -aes-256-cbc -pbkdf2 -iter 10000 -a -k "${passphrase}")
echo "Decrypted Content:"
echo "${decrText}"
echo


#Compose it into a new JSON in the standard message format
echo "New messages metadata JSON:"
jq ".\"674\".msg = ${decrText}" <<< "{}"
echo
97 changes: 97 additions & 0 deletions CIP-????/codesamples/democode-NODEJS.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
// -----------------------------------------------------------------------------------------------
// Demonstration implementation of CIP-0020 Transaction Messages Encryption/Decryption via NODE-JS
// -----------------------------------------------------------------------------------------------

const crypto = require('crypto');

//
// Calculate the KeyIV via the PasswordBasedKeyDerivedFormat2 pbkdf2 method, 10000 iterations, 48 bytes long, sha256
//
function calc_KeyIV(passphrase, salt) { //passphrase as utf8 string, salt as hexstring
const key_IV = crypto.pbkdf2Sync(Buffer.from(passphrase,'utf8'), Buffer.from(salt,'hex'), 10000, 48, 'sha256').toString('hex')
console.log(` keyIV: ${key_IV}`);
return key_IV; //hex-string
}

//
// Encryption Function
//
function encryptCardanoMessage(decrypted_msg, passphrase = 'cardano') { //decrypted_msg as utf8 string, passphrase as utf8 string(defaults to cardano)
//Encrypted Message (salted) looks like 'Salted__' + 8 bytes salt + cyphertext
//Build up the encrypted Message as hex string
var encrypted_hex = Buffer.from('Salted__','utf8').toString('hex');
//Generate the random salt
var salt = crypto.randomBytes(8).toString('hex');
encrypted_hex += salt; //append the salt
console.log(` salt: ${salt}`);
//Calculate the Key+IV
var keyIV = calc_KeyIV(passphrase, salt)
//The key itself is the first 32 Bytes (char 0-64 in hex string)
var key = keyIV.substring(0,64);
//The IV (initialization vector) is 16 Bytes and follows the key
var iv = keyIV.substring(64);
console.log(` key: ${key}`);
console.log(` iv: ${iv}`);
//Encrypt the message
const cipher = crypto.createCipheriv('aes-256-cbc', Buffer.from(key,'hex'), Buffer.from(iv,'hex'));
try {
var cyphertext = cipher.update(decrypted_msg, 'utf8', 'hex') + cipher.final('hex');
} catch (error) { console.error(`Could not encrypt the message\n${error}`); process.exit(1); }
console.log(` cyphertext: ${cyphertext}`);
encrypted_hex += cyphertext; //append the cyphertext
console.log(` Enc-Message(hex): ${encrypted_hex}`);
return Buffer.from(encrypted_hex,'hex').toString('base64'); //base64 string
}


//
// Decryption Function
//
function decryptCardanoMessage(encrypted_msg, passphrase = 'cardano') { //encrypted_msg as base64 string, passphrase as utf8 string(defaults to cardano)
//Encrypted Message is base64 encoded, convert it to hex
const encrypted_hex = Buffer.from(encrypted_msg, 'base64').toString('hex');
console.log(` Enc-Message(hex): ${encrypted_hex}`);
//Encrypted Message (salted) looks like 'Salted__' + 8 bytes salt + cyphertext
//Salt is byte 9-16 in the Encrypted Message (char 16-32 in a hex string)
var salt = encrypted_hex.substring(16,32);
console.log(` salt: ${salt}`);
//Cyphertext is all the rest after the salt (starting with char 32 in a hex string)
var cyphertext = encrypted_hex.substring(32);
console.log(` cyphertext: ${cyphertext}`);
//Calculate the Key+IV
var keyIV = calc_KeyIV(passphrase, salt)
//The key itself is the first 32 Bytes (char 0-64 in hex string)
var key = keyIV.substring(0,64);
//The IV (initialization vector) is 16 Bytes and follows the key
var iv = keyIV.substring(64);
console.log(` key: ${key}`);
console.log(` iv: ${iv}`);
//Decrypt the cyphertext with the key and the iv
const decipher = crypto.createDecipheriv('aes-256-cbc', Buffer.from(key,'hex'), Buffer.from(iv,'hex'));
try {
var decr_msg = decipher.update(cyphertext, 'hex').toString('utf8') + decipher.final('utf8');
} catch (error) { console.error(`Could not decrypt the message\n${error}`); process.exit(1); }
return decr_msg; //utf8
}

//-------------------------
// DEMO Encrypt and Decrypt
//-------------------------

const passphrase = 'cardano'; //Using default passphrase 'cardano'

// Encryption
console.log(`--- Encryption ---`);
var decrypted_msg = 'Hi, this is a test-message. Best regards, Martin';
console.log(` Dec-Message(utf8): ${decrypted_msg}`)
var encrypted_msg = encryptCardanoMessage(decrypted_msg, passphrase);
console.log(`Enc-Message(base64): ${encrypted_msg}`);
console.log(`\n\n`);

// Decryption
console.log(`--- Decryption ---`);
var encrypted_msg = 'U2FsdGVkX18UshV/vpKWoYtutcS2efoloN+okKMY+pYdvUnqi88znUhHPxSSX8t4';
console.log(`Enc-Message(base64): ${encrypted_msg}`);
var decrypted_msg = decryptCardanoMessage(encrypted_msg, passphrase);
console.log(` Dec-Message(utf8): ${decrypted_msg}`)
console.log(`\n\n`);
88 changes: 88 additions & 0 deletions CIP-????/codesamples/democode-PHP.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
// ------------------------------------------------------------------------------------------
// Demonstration implementation of CIP-0020 Transaction Messages Encryption/Decryption via PHP
// ------------------------------------------------------------------------------------------

<?php

const debug = true;

function elapsedTime($start) {
$elapsed = microtime(true) - $start;
if ($elapsed < 1) {
return ($elapsed * 1000) . " milliseconds";
} else if ($elapsed > 60) {
return ($elapsed / 60) . " minutes";
} else {
return $elapsed . " seconds";
}
}

function getPbkdf2($password, $salt, $iterations) {
return openssl_pbkdf2($password, $salt, 48, $iterations, 'sha256');
}

function encryptCardanoMessage($msg, $password = 'cardano', $iterations = 10000) {
if (debug) {
$start = microtime(true);
}
$salt = openssl_random_pseudo_bytes(8);
$encryptedText = "Salted__" . $salt;

$keyIV = getPbkdf2($password, $salt, $iterations);
$key = substr($keyIV, 0, 32);
$iv = substr($keyIV, 32);

$encryptedText .= openssl_encrypt($msg, 'aes-256-cbc', $key, OPENSSL_RAW_DATA, $iv);
$hashedEncryptedText = base64_encode($encryptedText);

if (debug) {
echo "Done encrypting message in " . elapsedTime($start) . "\r\n";
}

return $hashedEncryptedText;
}

function decryptCardanoMessage($msg, $password = 'cardano', $iterations = 10000) {
if (debug) {
$start = microtime(true);
}

$encryptedText = base64_decode($msg);
$salt = substr($encryptedText, 8, 8);
$cyphertext = substr($encryptedText, 16);

$keyIV = getPbkdf2($password, $salt, $iterations);
$key = substr($keyIV, 0, 32);
$iv = substr($keyIV, 32);

$decrypted = openssl_decrypt($cyphertext, 'aes-256-cbc', $key, OPENSSL_RAW_DATA, $iv);

if (debug) {
echo "Done decrypting message in " . elapsedTime($start) . "\r\n";
}

return $decrypted;
}

$payload = "Testing message signing...";

// Basic signed/encrypted message w/ default password of "cardano"
$signed = encryptCardanoMessage($payload);

// Basic signed/encrypted message w/ custom password
$passwordSigned = encryptCardanoMessage($payload, "You'll never guess it!");

// Basic signed/encrypted message w/ custom password and fewer iterations
$shortPasswordSigned = encryptCardanoMessage($payload, "Please", 20);

// Basic decoding w/ default password of "cardano"
$unsigned = decryptCardanoMessage($signed);
echo "\$signed is: {$unsigned}\r\n";

// Basic decoding w/ custom password
$unsignedPassword = decryptCardanoMessage($passwordSigned, "You'll never guess it!");
echo "\$passwordSigned is: {$unsignedPassword}\r\n";

// Basic decoding w/ custom password and fewer iterations
$shortUnsigned = decryptCardanoMessage($shortPasswordSigned, "Please", 20);
echo "\$shortPasswordSigned is: {$shortUnsigned}\r\n";
42 changes: 42 additions & 0 deletions CIP-????/codesamples/democode-WEB.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// -----------------------------------------------------------------------------------------------
// Democode for running a Decryption on the Web Frontend - Method BASIC
// -----------------------------------------------------------------------------------------------

// Library that is used for this codesample: https://www.npmjs.com/package/crypto-js
// Just import it before using this code

let encrypted = "U2FsdGVkX18IJMMB5MDfNmuvvlbu4m5ODGmCrHHtWfYKarTRT4/x790+uhsj7cgRxDFvjxU7dcSPqH5PAXvRtPcaRyqoYBaXOQbm3D78wQCY4wCiLF1/mFOvFHPfpQHeC9jykRfpaVC3rtlJdHCPTw=="
let encryptedWA = cryptoJS.enc.Base64.parse(encrypted);

// Split the encrypted data into the individual pieces
let prefixWA = cryptoJS.lib.WordArray.create(encryptedWA.words.slice(0, 8/4)); // Salted__ prefix
let saltWA = cryptoJS.lib.WordArray.create(encryptedWA.words.slice(8/4, 16/4)); // 8 bytes salt: 0x0123456789ABCDEF
let ciphertextWA = cryptoJS.lib.WordArray.create(encryptedWA.words.slice(16/4, encryptedWA.words.length)); // ciphertext

// Determine key and IV using PBKDF2
let password = 'cardano'
let keyIvWA = cryptoJS.PBKDF2(
password,
saltWA,
{
keySize: (32+16)/4, // key and IV
iterations: 10000,
hasher: cryptoJS.algo.SHA256
}
);
let keyWA = cryptoJS.lib.WordArray.create(keyIvWA.words.slice(0, 32/4));
let ivWA = cryptoJS.lib.WordArray.create(keyIvWA.words.slice(32/4, (32+16)/4));

// Decrypt the data
let decryptedWA = cryptoJS.AES.decrypt(
{
ciphertext: ciphertextWA},
keyWA,
{iv: ivWA}
);
let decrypted = decryptedWA.toString(cryptoJS.enc.Utf8)

console.log(`Encrypted Data:`)
console.log(encrypted)
console.log(`Decrypted Data:`)
console.log(decrypted)
11 changes: 11 additions & 0 deletions CIP-????/codesamples/encrypted-message-metadata.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"674":
{
"enc": "basic",
"msg":
[
"U2FsdGVkX1/5Y0A7l8xK686rvLsmPviTlna2n3P/ADNm89Ynr1UPZ/Q6bynbe28Y",
"/zWYOB9PAGt+bq1L0z/W2LNHe92HTN/Fwz16aHa98TOsgM3q8tAR4NSqrLZVu1H7"
]
}
}
5 changes: 5 additions & 0 deletions CIP-????/codesamples/normal-message-metadata.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"674": {
"msg": ["Invoice-No: 123456789","Order-No: 7654321","Email: john@doe.com"]
}
}