This commit is contained in:
eschorn1 2024-03-14 08:46:53 -05:00
parent 98fc10359f
commit 20a8263d42
11 changed files with 238 additions and 0 deletions

View file

@ -49,6 +49,10 @@ name = "benchmark"
harness = false harness = false
[profile.dev]
opt-level = 3
[profile.bench] [profile.bench]
debug = true debug = true
debug-assertions = false debug-assertions = false

View file

@ -229,6 +229,14 @@ impl Adrs {
pub(crate) fn set_tree_index(&mut self, i: u32) { self.f7 = i.to_be_bytes() } pub(crate) fn set_tree_index(&mut self, i: u32) { self.f7 = i.to_be_bytes() }
#[cfg(any(
feature = "slh_dsa_shake_128f",
feature = "slh_dsa_shake_128s",
feature = "slh_dsa_shake_192f",
feature = "slh_dsa_shake_192s",
feature = "slh_dsa_shake_256f",
feature = "slh_dsa_shake_256s"
))]
pub(crate) fn to_32_bytes(&self) -> [u8; 32] { pub(crate) fn to_32_bytes(&self) -> [u8; 32] {
let mut ret = [0u8; 32]; let mut ret = [0u8; 32];
let mut start = 0; let mut start = 0;
@ -241,6 +249,14 @@ impl Adrs {
ret ret
} }
#[cfg(any(
feature = "slh_dsa_sha2_128f",
feature = "slh_dsa_sha2_128s",
feature = "slh_dsa_sha2_192f",
feature = "slh_dsa_sha2_192s",
feature = "slh_dsa_sha2_256f",
feature = "slh_dsa_sha2_256s"
))]
pub(crate) fn to_22_bytes(&self) -> [u8; 22] { pub(crate) fn to_22_bytes(&self) -> [u8; 22] {
let mut ret = [0u8; 22]; let mut ret = [0u8; 22];
ret[0] = self.f0[3]; ret[0] = self.f0[3];

18
tests/messages.rs Normal file

File diff suppressed because one or more lines are too long

38
wasm/Cargo.toml Normal file
View file

@ -0,0 +1,38 @@
[package]
name = "wasm"
version = "0.1.2"
authors = ["Eric Schorn <eschorn@integritychain.com>"]
description = "Sample web page utilizing FIPS 205 code"
repository = ""
license = "MIT OR Apache-2.0"
publish = false
edition = "2021"
[lib]
crate-type = ["cdylib", "rlib"]
[features]
default = ["console_error_panic_hook"]
[dependencies]
wasm-bindgen = "0.2.84"
fips205 = { path = "../../fips205", default-features = false, features = ["slh_dsa_sha2_128f"] }
rand_chacha = "0.3.1"
# The `console_error_panic_hook` crate provides better debugging of panics by
# logging them with `console.error`. This is great for development, but requires
# all the `std::fmt` and `std::panicking` infrastructure, so isn't great for
# code size when deploying.
console_error_panic_hook = { version = "0.1.7", optional = true }
#rand = { version = "0.9.0-alpha.0" , features = ["js"]}
rand = "0.8.5"
getrandom = { version = "0.2", features = ["js"] }
hex = "0.4.3"
[dev-dependencies]
wasm-bindgen-test = "0.3.34"
[profile.release]
# Tell `rustc` to optimize for small code size.
opt-level = "s"

21
wasm/README.md Normal file
View file

@ -0,0 +1,21 @@
One-off installation
~~~
$ cargo install wasm-pack
$ sudo npm install npm@latest -g
~~~
To run:
~~~
$ cd wasm # this directory
$ wasm-pack build
$ cd www
$ npm install
$ export NODE_OPTIONS=--openssl-legacy-provider
$ npm run start
go to http://localhost:8080/
~~~

29
wasm/src/lib.rs Normal file
View file

@ -0,0 +1,29 @@
use wasm_bindgen::prelude::*;
use rand_chacha::rand_core::SeedableRng;
use fips205::slh_dsa_sha2_128f;
use fips205::traits::{SerDes, Signer, Verifier};
#[wasm_bindgen]
pub fn sign(message: &str) -> String {
let seed = 123;
let mut rng = rand_chacha::ChaCha8Rng::seed_from_u64(seed);
let randomize = true;
let (pk, sk) = slh_dsa_sha2_128f::try_keygen_with_rng_vt(&mut rng).expect("keygen failed");
let sig = sk.try_sign_with_rng_ct(&mut rng, message.as_ref(), randomize).expect("sign failed");
assert!(pk.try_verify_vt(message.as_ref(), &sig).expect("verify error"), "verify failed");
let sk_hex = hex::encode(&sk.into_bytes());
let sig_hex = hex::encode(&sig);
let pk_hex = hex::encode(&pk.into_bytes());
let s0 = format!("The message to sign is: {}\n", message);
let s1 = format!("The seed used to generate the keys is: {}\n\n", seed);
let s2 = format!("The generated public||private key is: {}\n", sk_hex);
let s3 = format!("Using that private key, the calculated signature is: {}\n\n", sig_hex);
let s4 = format!("The generated public key is: {}\n", pk_hex);
let s5 = "The public key verifies the signature on the message."; // because the above assert! passed
(s0 + &s1 + &s2 + &s3 + &s4 + &s5).into()
}

5
wasm/www/bootstrap.js vendored Normal file
View file

@ -0,0 +1,5 @@
// A dependency graph that contains any wasm must all be imported
// asynchronously. This `bootstrap.js` file does the single async import, so
// that no one else needs to worry about it again.
import("./index.js")
.catch(e => console.error("Error importing `index.js`:", e));

36
wasm/www/index.html Normal file
View file

@ -0,0 +1,36 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>FIPS 205 WASM Demo</title>
<link rel="stylesheet" href="https://cdn.simplecss.org/simple.min.css">
<style> body {grid-template-columns: 1fr min(60rem,90%) 1fr;}</style>
</head>
<body>
<noscript>This page contains webassembly and javascript content, please enable javascript in your browser.</noscript>
<h1>FIPS 205 WASM Demo</h1>
<p>This page is a simple demonstration of code from the <a href="https://crates.io/crates/fips204">FIPS 205
Rust crate</a> running in the browser via wasm. This demo has a hardcoded random number generator so that
its results can be compared to <a href="https://github.com/integritychain/fips205/blob/main/tests/messages.rs">
native test cases.</a> Please see section 3.1 of the
<a href="https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.205.ipd.pdf">FIPS 205 standard</a> for critical
requirements on randomness when utilizing FIPS 205 in production.
</p>
<p>Enter a message to sign below and click on 'Submit'. Keys will be generated, the message signed, and results
displayed.</p>
<p><form action="" id="wasmForm">
<input type="text" id="message" class="form-control" placeholder="Enter a message to sign...">
<button type="submit">Submit</button>
</form></p>
<pre id="wasm-canvas"></pre>
<script src="./bootstrap.js"></script>
</body>
</html>

18
wasm/www/index.js Normal file
View file

@ -0,0 +1,18 @@
import * as wasm from "wasm";
let wasmForm = document.getElementById("wasmForm");
wasmForm.addEventListener("submit", (e) => {
e.preventDefault();
let message = document.getElementById("message");
let result = "";
if (message.value) {
result = wasm.sign(message.value);
message.value = "";
document.getElementById("wasm-canvas").innerHTML = result;
} else {
alert("Please enter a non-empty message");
}
});

39
wasm/www/package.json Normal file
View file

@ -0,0 +1,39 @@
{
"name": "create-wasm-app",
"version": "0.1.0",
"description": "create an app to consume rust-generated wasm packages",
"main": "index.js",
"bin": {
"create-wasm-app": ".bin/create-wasm-app.js"
},
"scripts": {
"build": "webpack --config webpack.config.js",
"start": "webpack-dev-server"
},
"repository": {
"type": "git",
"url": "git+https://github.com/rustwasm/create-wasm-app.git"
},
"keywords": [
"webassembly",
"wasm",
"rust",
"webpack"
],
"author": "Ashley Williams <ashley666ashley@gmail.com>",
"license": "(MIT OR Apache-2.0)",
"bugs": {
"url": "https://github.com/rustwasm/create-wasm-app/issues"
},
"homepage": "https://github.com/rustwasm/create-wasm-app#readme",
"dependencies": {
"wasm": "file:../pkg"
},
"devDependencies": {
"hello-wasm-pack": "^0.1.0",
"webpack": "^4.29.3",
"webpack-cli": "^3.1.0",
"webpack-dev-server": "^3.1.5",
"copy-webpack-plugin": "^5.0.0"
}
}

View file

@ -0,0 +1,14 @@
const CopyWebpackPlugin = require("copy-webpack-plugin");
const path = require('path');
module.exports = {
entry: "./bootstrap.js",
output: {
path: path.resolve(__dirname, "dist"),
filename: "bootstrap.js",
},
mode: "development",
plugins: [
new CopyWebpackPlugin(['index.html'])
],
};