Skip to content

Commit

Permalink
Extend vetKD example dapps with identity-based encryption (IBE) (#603)
Browse files Browse the repository at this point in the history
Extend the vetKD example dapps (both for Rust and Motoko) to demo identity-based encryption (IBE).
  • Loading branch information
fspreiss authored Aug 9, 2023
1 parent aea37e7 commit 8065c3e
Show file tree
Hide file tree
Showing 13 changed files with 345 additions and 19 deletions.
Binary file modified motoko/vetkd/ic-vetkd-utils-0.1.0.tgz
Binary file not shown.
2 changes: 1 addition & 1 deletion motoko/vetkd/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

19 changes: 19 additions & 0 deletions motoko/vetkd/src/app_backend/Main.mo
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,23 @@ actor {
});
Hex.encode(Blob.toArray(encrypted_key));
};

public shared ({ caller }) func ibe_encryption_key() : async Text {
let { public_key } = await vetkd_system_api.vetkd_public_key({
canister_id = null;
derivation_path = Array.make(Text.encodeUtf8("ibe_encryption"));
key_id = { curve = #bls12_381; name = "test_key_1" };
});
Hex.encode(Blob.toArray(public_key));
};

public shared ({ caller }) func encrypted_ibe_decryption_key_for_caller(encryption_public_key : Blob) : async Text {
let { encrypted_key } = await vetkd_system_api.vetkd_encrypted_key({
derivation_id = Principal.toBlob(caller);
public_key_derivation_path = Array.make(Text.encodeUtf8("ibe_encryption"));
key_id = { curve = #bls12_381; name = "test_key_1" };
encryption_public_key;
});
Hex.encode(Blob.toArray(encrypted_key));
};
};
29 changes: 29 additions & 0 deletions motoko/vetkd/src/app_frontend_js/assets/main.css
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,33 @@ button[type="submit"] {

#vetkddemo {
text-align: center;
}

#ibedemo {
text-align: center;
margin-top: 2em;
}

#get_symmetric_key_result {
text-align: center;
}

#ibe_encrypt_result {
text-align: center;
}

#encrypt_result {
text-align: center;
}

#decrypt_result {
text-align: center;
}

#ibe_encrypt_result {
text-align: center;
}

#ibe_decrypt_result {
text-align: center;
}
25 changes: 18 additions & 7 deletions motoko/vetkd/src/app_frontend_js/src/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -12,27 +12,38 @@

<body>
<main>
<h1 id="vetkddemo">vetKD Demo</h1>
<hr />
<h1 id="vetkddemo">vetKD Demo: Encryption with symmetric (AES-GCM-256) key</h1>
<form action="#" id="get_symmetric_key_form">
<button type="submit">Get symmetric key</button>
<button type="submit">Fetch symmetric key for local usage</button>
</form>
<section id="get_symmetric_key_result"></section>
<hr />
<form action="#" id="encrypt_form">
<label for="plaintext">Plaintext:</label>
<input type="text" id="plaintext"><br><br>
<button type="submit" id="submit_plaintext" disabled="true">Use key to encrypt</button>
<button type="submit" id="submit_plaintext" disabled="true">Encrypt with symmetric key</button>
</form>
<section id="encrypt_result"></section>
<hr />
<form action="#" id="decrypt_form">
<label for="ciphertext">Ciphertext:</label>
<input type="text" id="ciphertext"><br><br>
<button type="submit" id="submit_ciphertext" disabled="true">Use key and decrypt</button>
<button type="submit" id="submit_ciphertext" disabled="true">Decrypt with symmetric key</button>
</form>
<section id="decrypt_result"></section>
<hr />
<h1 id="ibedemo">vetKD Demo: Identity-Based Encryption (IBE)</h1>
<form action="#" id="ibe_encrypt_form">
<label for="ibe_plaintext">Plaintext:</label>
<input type="text" id="ibe_plaintext"><br><br>
<button type="submit" id="ibe_encrypt" disabled="true">IBE-encrypt for myself</button>
</form>
<section id="ibe_encrypt_result"></section>
<form action="#" id="ibe_decrypt_form">
<label for="ibe_ciphertext">Ciphertext:</label>
<input type="text" id="ibe_ciphertext"><br><br>
<button type="submit" id="ibe_decrypt" disabled="true">IBE-decrypt for myself</button>
</form>
<section id="ibe_decrypt_result"></section>
<hr />
<img src="logo2.svg" id="builtonchainlogo" />
</main>
</body>
Expand Down
95 changes: 94 additions & 1 deletion motoko/vetkd/src/app_frontend_js/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ document.getElementById("get_symmetric_key_form").addEventListener("submit", asy

result.innerText = "Fetching symmetric key...";
const aes_256_key = await get_aes_256_gcm_key();
result.innerText = "aes_256_key: " + hex_encode(aes_256_key);
result.innerText = "Done. AES-GCM-256 key available for local usage.";

button.removeAttribute("disabled");

Expand Down Expand Up @@ -123,6 +123,99 @@ async function aes_gcm_decrypt(ciphertext_hex, rawKey) {
return new TextDecoder().decode(decrypted);
}

document.getElementById("ibe_encrypt_form").addEventListener("submit", async (e) => {
e.preventDefault();
const button = e.target.querySelector("button");
button.setAttribute("disabled", true);
const result = document.getElementById("ibe_encrypt_result");

const ibe_ciphertext = await ibe_encrypt(document.getElementById("ibe_plaintext").value);
result.innerText = "IBE ciphertext: " + ibe_ciphertext;

button.removeAttribute("disabled");
return false;
});

document.getElementById("ibe_decrypt_form").addEventListener("submit", async (e) => {
e.preventDefault();
const button = e.target.querySelector("button");
button.setAttribute("disabled", true);
const result = document.getElementById("ibe_decrypt_result");

const ibe_plaintext = await ibe_decrypt(document.getElementById("ibe_ciphertext").value);
result.innerText = "IBE plaintext: " + ibe_plaintext;

button.removeAttribute("disabled");
return false;
});

document.getElementById("ibe_plaintext").addEventListener("keyup", async (e) => {
update_ibe_encrypt_button_state();
});

document.getElementById("ibe_ciphertext").addEventListener("keyup", async (e) => {
update_ibe_decrypt_button_state();
});

function update_ibe_encrypt_button_state() {
const ibe_encrypt_button = document.getElementById("ibe_encrypt");
if (document.getElementById("ibe_plaintext").value === "") {
ibe_encrypt_button.setAttribute("disabled", true);
} else {
ibe_encrypt_button.removeAttribute("disabled");
}
}

function update_ibe_decrypt_button_state() {
const ibe_decrypt_button = document.getElementById("ibe_decrypt");
if (document.getElementById("ibe_ciphertext").value === "") {
ibe_decrypt_button.setAttribute("disabled", true);
} else {
ibe_decrypt_button.removeAttribute("disabled");
}
}

async function ibe_encrypt(message) {
document.getElementById("ibe_encrypt_result").innerText = "Fetching IBE encryption key..."
const pk_bytes_hex = await app_backend.ibe_encryption_key();

document.getElementById("ibe_encrypt_result").innerText = "Preparing IBE-encryption..."
const app_backend_principal = await agent.Actor.agentOf(app_backend).getPrincipal(); // default is the anonymous principal!
const message_encoded = new TextEncoder().encode(message);
const seed = window.crypto.getRandomValues(new Uint8Array(32));

document.getElementById("ibe_encrypt_result").innerText = "IBE-encrypting..."
const ibe_ciphertext = vetkd.IBECiphertext.encrypt(
hex_decode(pk_bytes_hex),
app_backend_principal.toUint8Array(),
message_encoded,
seed
);
return hex_encode(ibe_ciphertext.serialize());
}

async function ibe_decrypt(ibe_ciphertext_hex) {
document.getElementById("ibe_decrypt_result").innerText = "Preparing IBE-decryption..."
const tsk_seed = window.crypto.getRandomValues(new Uint8Array(32));
const tsk = new vetkd.TransportSecretKey(tsk_seed);
document.getElementById("ibe_decrypt_result").innerText = "Fetching IBE decryption key..."
const ek_bytes_hex = await app_backend.encrypted_ibe_decryption_key_for_caller(tsk.public_key());
document.getElementById("ibe_decrypt_result").innerText = "Fetching IBE enryption key (needed for verification)..."
const pk_bytes_hex = await app_backend.ibe_encryption_key();

const app_backend_principal = await agent.Actor.agentOf(app_backend).getPrincipal(); // default is the anonymous principal!

const k_bytes = tsk.decrypt(
hex_decode(ek_bytes_hex),
hex_decode(pk_bytes_hex),
app_backend_principal.toUint8Array()
);

const ibe_ciphertext = vetkd.IBECiphertext.deserialize(hex_decode(ibe_ciphertext_hex));
const ibe_plaintext = ibe_ciphertext.decrypt(k_bytes);
return new TextDecoder().decode(ibe_plaintext);
}

const hex_decode = (hexString) =>
Uint8Array.from(hexString.match(/.{1,2}/g).map((byte) => parseInt(byte, 16)));
const hex_encode = (bytes) =>
Expand Down
Binary file modified rust/vetkd/ic-vetkd-utils-0.1.0.tgz
Binary file not shown.
2 changes: 1 addition & 1 deletion rust/vetkd/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

39 changes: 39 additions & 0 deletions rust/vetkd/src/app_backend/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,45 @@ async fn encrypted_symmetric_key_for_caller(encryption_public_key: Vec<u8>) -> S
hex::encode(response.encrypted_key)
}

#[update]
async fn ibe_encryption_key() -> String {
let request = VetKDPublicKeyRequest {
canister_id: None,
derivation_path: vec![b"ibe_encryption".to_vec()],
key_id: bls12_381_test_key_1(),
};

let (response,): (VetKDPublicKeyReply,) = ic_cdk::api::call::call(
vetkd_system_api_canister_id(),
"vetkd_public_key",
(request,),
)
.await
.expect("call to vetkd_public_key failed");

hex::encode(response.public_key)
}

#[update]
async fn encrypted_ibe_decryption_key_for_caller(encryption_public_key: Vec<u8>) -> String {
let request = VetKDEncryptedKeyRequest {
derivation_id: ic_cdk::caller().as_slice().to_vec(),
public_key_derivation_path: vec![b"ibe_encryption".to_vec()],
key_id: bls12_381_test_key_1(),
encryption_public_key,
};

let (response,): (VetKDEncryptedKeyReply,) = ic_cdk::api::call::call(
vetkd_system_api_canister_id(),
"vetkd_encrypted_key",
(request,),
)
.await
.expect("call to vetkd_encrypted_key failed");

hex::encode(response.encrypted_key)
}

fn bls12_381_test_key_1() -> VetKDKeyId {
VetKDKeyId {
curve: VetKDCurve::Bls12_381,
Expand Down
2 changes: 2 additions & 0 deletions rust/vetkd/src/app_backend/vetkd_app_backend.did
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
service : {
"encrypted_symmetric_key_for_caller" : (blob) -> (text);
"symmetric_key_verification_key" : () -> (text);
"encrypted_ibe_decryption_key_for_caller" : (blob) -> (text);
"ibe_encryption_key" : () -> (text);
};
29 changes: 29 additions & 0 deletions rust/vetkd/src/app_frontend_js/assets/main.css
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,33 @@ button[type="submit"] {

#vetkddemo {
text-align: center;
}

#ibedemo {
text-align: center;
margin-top: 2em;
}

#get_symmetric_key_result {
text-align: center;
}

#ibe_encrypt_result {
text-align: center;
}

#encrypt_result {
text-align: center;
}

#decrypt_result {
text-align: center;
}

#ibe_encrypt_result {
text-align: center;
}

#ibe_decrypt_result {
text-align: center;
}
27 changes: 19 additions & 8 deletions rust/vetkd/src/app_frontend_js/src/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -12,29 +12,40 @@

<body>
<main>
<h1 id="vetkddemo">vetKD Demo</h1>
<hr />
<h1 id="vetkddemo">vetKD Demo: Encryption with symmetric (AES-GCM-256) key</h1>
<form action="#" id="get_symmetric_key_form">
<button type="submit">Get symmetric key</button>
<button type="submit">Fetch symmetric key for local usage</button>
</form>
<section id="get_symmetric_key_result"></section>
<hr />
<form action="#" id="encrypt_form">
<label for="plaintext">Plaintext:</label>
<input type="text" id="plaintext"><br><br>
<button type="submit" id="submit_plaintext" disabled="true">Use key to encrypt</button>
<button type="submit" id="submit_plaintext" disabled="true">Encrypt with symmetric key</button>
</form>
<section id="encrypt_result"></section>
<hr />
<form action="#" id="decrypt_form">
<label for="ciphertext">Ciphertext:</label>
<input type="text" id="ciphertext"><br><br>
<button type="submit" id="submit_ciphertext" disabled="true">Use key and decrypt</button>
<button type="submit" id="submit_ciphertext" disabled="true">Decrypt with symmetric key</button>
</form>
<section id="decrypt_result"></section>
<hr />
<h1 id="ibedemo">vetKD Demo: Identity-Based Encryption (IBE)</h1>
<form action="#" id="ibe_encrypt_form">
<label for="ibe_plaintext">Plaintext:</label>
<input type="text" id="ibe_plaintext"><br><br>
<button type="submit" id="ibe_encrypt" disabled="true">IBE-encrypt for myself</button>
</form>
<section id="ibe_encrypt_result"></section>
<form action="#" id="ibe_decrypt_form">
<label for="ibe_ciphertext">Ciphertext:</label>
<input type="text" id="ibe_ciphertext"><br><br>
<button type="submit" id="ibe_decrypt" disabled="true">IBE-decrypt for myself</button>
</form>
<section id="ibe_decrypt_result"></section>
<hr />
<img src="logo2.svg" id="builtonchainlogo" />
</main>
</body>

</html>
</html>
Loading

0 comments on commit 8065c3e

Please sign in to comment.