Public
Edited
Nov 29, 2023
Insert cell
Insert cell
mt = import('https://cdn.jsdelivr.net/npm/merkletreejs@0.3.11/+esm')
Insert cell
cryptojs = (await import('https://cdn.jsdelivr.net/npm/crypto-js@4.2.0/+esm')).default
Insert cell
MerkleTree = mt.MerkleTree
Insert cell
SHA256 = cryptojs.SHA256
Insert cell
RIPEMD160 = cryptojs.RIPEMD160
Insert cell
tree = new MerkleTree ([SHA256('lindsay'), SHA256('bob'), SHA256('jess')], SHA256)
Insert cell
tree.toString()
Insert cell
proof = tree.getProof(SHA256('bob'))
Insert cell
root = tree.getRoot().toString('hex')
Insert cell
SHA256('lindsay').toString()
Insert cell
SHA256('bob').toString()
Insert cell
verified = tree.verify(proof, SHA256('bob'), root)
Insert cell
bobJect = {
return {id: 'bob-dream'}
}
Insert cell
bobJectJSON = JSON.stringify(bobJect)
Insert cell
backToBobJect = JSON.parse(bobJectJSON)
Insert cell
SHA256(bobJectJSON).toString()
Insert cell
passportData = {

let names = ['b', 'bob', 'bob-dream', 'bob-dream-aries'] // common names

let uniqueIds = ['NO14hzv0CbGqK0PJx_OhK'] // probabalistically unique ids, generated per passport protocol, nanoid()

let emails = ['bob@email.com', 'b@mail.io'] // to be verified against the network "verification" chain

let handles = [{service: "github", id: "mullojo"}] // to be verified against the network "verification" chain

let verifications = [{type: 'email', key: 'bob@email.com', verif: 'verifNetHash2323r23fsfee'}] // supplied by network verification chainn

// verif types: email, OAuth, personal, etc

let nameList = names.map(name => {return {name}})
let uidList = uniqueIds.map(uid => {return {uid}})
let emailList = emails.map(email => {return {email}})
let handleList = handles.map(handle => {return {handle}})
let verifList = verifications.map(verif => {return {verif}})

let leafs = nameList.concat(uidList).concat(emailList).concat(handleList).concat(verifList)

return leafs;
}
Insert cell
passportDataJSON = passportData.map(row => JSON.stringify(row))
Insert cell
passportLeafs = passportDataJSON.map(row => SHA256(row))
Insert cell
passportLeafStrings = passportLeafs.map(row => row.toString())
Insert cell
passportLeafStringRIPEMD160 = passportLeafStrings.map(row => RIPEMD160(row).toString())
Insert cell
passportTree = new MerkleTree (passportLeafs, SHA256)
Insert cell
passportTree.toString()
Insert cell
Insert cell
RIPEMD160(SHA256("{\"name\":\"b\"}").toString()).toString()
Insert cell
Insert cell
keyPair = crypto.subtle.generateKey(
{ name: 'ECDSA', namedCurve: 'P-256' },
true, // extractable
['sign', 'verify']
)
Insert cell
signature = {
// private key is in keyPair.privateKey
// public key is in keyPair.publicKey
// Sign the data using the private key
let dataToSign = 'JSON data'; // typically "leaf" hash
let textEncoder = new TextEncoder();
let dataBuffer = textEncoder.encode(dataToSign);
return crypto.subtle.sign(
{ name: 'ECDSA', hash: { name: 'SHA-256' } },
keyPair.privateKey,
dataBuffer
)
}
Insert cell
// Example of some "signed data" that could be represented in this "short" RIPEMD160 format
RIPEMD160(signature).toString()
Insert cell
publicKeyJWK = crypto.subtle.exportKey('jwk', keyPair.publicKey)
Insert cell
pubKeyJwkJSON = JSON.stringify(publicKeyJWK)
Insert cell
// Import the public key from JWK format
importedPublicKey = crypto.subtle.importKey(
'jwk',
publicKeyJWK,
{ name: 'ECDSA', namedCurve: 'P-256' },
true, // extractable
['verify']
)
Insert cell
verifStatus = {
// Step 2: Verify the signature using the public key
let dataToVerify = 'JSON data'; // typically "leaf" hash
let textEncoder = new TextEncoder();
let dataBuffer = textEncoder.encode(dataToVerify);

// Assuming 'signature' is the signature previously generated
return crypto.subtle.verify(
{ name: 'ECDSA', hash: { name: 'SHA-256' } },
keyPair.publicKey,
signature,
dataBuffer
)
}
Insert cell
verifStatusImport = {
// Step 2: Verify the signature using the public key
let dataToVerify = 'JSON data'; // typically "leaf" hash
let textEncoder = new TextEncoder();
let dataBuffer = textEncoder.encode(dataToVerify);

// Assuming 'signature' is the signature previously generated
return crypto.subtle.verify(
{ name: 'ECDSA', hash: { name: 'SHA-256' } },
importedPublicKey,
signature,
dataBuffer
)
}
Insert cell
Insert cell
keyMaterial = {
// Replace 'yourSecretPassphrase' with your actual secret passphrase
let secretPassphrase = 'someOtherSecretPassPhrase';
// Convert the passphrase to an ArrayBuffer
let passphraseBuffer = new TextEncoder().encode(secretPassphrase);
// Generate a key from the passphrase using a key derivation function (e.g., PBKDF2)
return crypto.subtle.importKey(
'raw',
passphraseBuffer,
{ name: 'PBKDF2' },
false,
['deriveBits', 'deriveKey']
)
}
Insert cell
encryptionKey = {

// Derive a key from the passphrase using PBKDF2
return crypto.subtle.deriveKey(
{ name: 'PBKDF2', salt: new Uint8Array(16), iterations: 100000, hash: 'SHA-256' },
keyMaterial,
{ name: 'AES-GCM', length: 256 },
false, // make it exportable ?
['encrypt', 'decrypt']
);

}
Insert cell
encryptedData = {

// Encrypt the text data
let textToEncrypt = 'Lots of JSON text data for passport in base64';
let textEncoder = new TextEncoder();
let plaintextBuffer = textEncoder.encode(textToEncrypt);
return crypto.subtle.encrypt(
{ name: 'AES-GCM', iv: new Uint8Array(12) },
encryptionKey,
plaintextBuffer
)
}
Insert cell
function arrayBufferToBase64(arrayBuffer) {
let binary = '';
let bytes = new Uint8Array(arrayBuffer);
let len = bytes.byteLength;

for (let i = 0; i < len; i++) {
binary += String.fromCharCode(bytes[i]);
}

return btoa(unescape(encodeURIComponent(binary)));
}
Insert cell
function base64ToArrayBuffer(base64) {
let binary = decodeURIComponent(escape(atob(base64)));
let len = binary.length;
let bytes = new Uint8Array(len);

for (let i = 0; i < len; i++) {
bytes[i] = binary.charCodeAt(i);
}

return bytes.buffer;
}
Insert cell
base64String = arrayBufferToBase64(encryptedData);
Insert cell
decodedBuffer = base64ToArrayBuffer(base64String);
Insert cell
encryptedData == decodedBuffer
Insert cell
{
/* Create a Blob from the ArrayBuffer
let blob = new Blob([encryptedData], { type: 'application/octet-stream' });
// Create a download link
let downloadLink = document.createElement('a');
downloadLink.href = window.URL.createObjectURL(blob);
downloadLink.download = 'bobs.passport'; // Specify the desired file name
// Trigger a click on the link to initiate the download
return downloadLink.click(); */
}
Insert cell
decryptedText = {

// Decrypt the data back to plaintext
return crypto.subtle.decrypt(
{ name: 'AES-GCM', iv: new Uint8Array(12) },
encryptionKey,
decodedBuffer // encryptedData
)
.then((decryptedBuffer) => {
let decryptedText = new TextDecoder().decode(decryptedBuffer);
return decryptedText;
})
}
Insert cell
jsonToBase64 = {
// Step 1: Convert JSON data to a JSON string
let jsonData = { key: 'value', number: 42 };
let jsonString = JSON.stringify(jsonData);
// Step 2: Convert the JSON string to Base64 (handle non-ASCII characters)
let base64String = btoa(unescape(encodeURIComponent(jsonString)));
return base64String;
}
Insert cell
base64ToJson = {
// Step 1: Decode the Base64 string to get the JSON string
let decodedString = decodeURIComponent(escape(atob(jsonToBase64)));
// Step 2: Parse the JSON string to get the original JavaScript object
let jsonData = JSON.parse(decodedString);
// Now 'jsonData' contains the original JavaScript object
return jsonData;
}
Insert cell
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more