Skip to content

Commit

Permalink
WIP: RND/RNDSIG validation implementation in java(left commented code…
Browse files Browse the repository at this point in the history
… for future reference, needs cleanup once completed)
  • Loading branch information
Maceeran committed Sep 14, 2024
1 parent abd57ee commit 32dd751
Show file tree
Hide file tree
Showing 2 changed files with 330 additions and 0 deletions.
1 change: 1 addition & 0 deletions core/src.ts/web/examples/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ <h1>LibHaLo Demos</h1>
<li><a href="get_data_struct.html">get_data_struct.html - Retrieve data demo</a></li>
<li><a href="get_key_info.html">get_key_info.html - Key slot information demo</a></li>
<li><a href="halo_bridge.html">halo_bridge.html - HaLo bridge demo</a></li>
<li><a href="rnd_rndsig_validation.html">rnd_rndsig_validation.html - RND/RNDSIG validation demo</a></li>
</ul>
</div>
</body>
Expand Down
329 changes: 329 additions & 0 deletions core/src.ts/web/examples/rnd_rndsig_validation.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,329 @@
<!DOCTYPE html>
<html>
<head>
<!--
LibHaLo - Programmatically interact with HaLo tags from the web browser, mobile application or the desktop.
Copyright by Arx Research, Inc., a Delaware corporation
License: MIT
-->
<title>LibHaLo Demo</title>

<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css"
integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" crossorigin="anonymous">

<script type="text/javascript">
// ensure the library is always fully reloaded
document.write('<script src="../dist/libhalo.js?_v=' + (
Math.random() + '') + '"></scr' + 'ipt>');
</script>
<script src="https://cdn.ethers.io/lib/ethers-5.2.umd.min.js"
type="application/javascript"></script>
<script src="
https://cdnjs.cloudflare.com/ajax/libs/elliptic/6.5.7/elliptic.min.js"></script>
<script src="
https://cdn.jsdelivr.net/npm/keccak256@1.0.6/keccak256.min.js
"></script>
<script src="
https://cdn.jsdelivr.net/npm/buffer@6.0.3/index.min.js
"></script>
<script src="
https://cdn.jsdelivr.net/npm/secp256k1@5.0.0/elliptic.min.js
"></script>
</head>
<body>
<div class="container">
<h1>LibHaLo Demo</h1>
<p class="text-muted">
<b>(Mobile only) RND/RNDSIG validation
</p>
<div class="mb-3">
<label class="form-label">URL</label>
<input type="text" class="form-control" id="url" value="https://eth.vrfy.ch/?av=A02.03.000001.390DE7BD&v=01.C8.000005.E582A2D2&pk1=04F80774B09C70BD8C572F57C2D05835D0E324BE9133B49285EAC24E177BC56D92BCF464C3B12CECE362D91FAF37D7ACBA0996C61922A3535CBAEA855416EA6034&pk2=0463D44E9708131505F8E8C5917DF96919624173EEF726DF3F0569865CE83BC9CD9A018879E56C2FF8DC12531A354A6E669714871D0A5F2B5D63E100E98F930DA5&rnd=00000001FBAD9E01AA882F8669123390768FC8AF11916589DF638787A2C2700A&rndsig=304502203D6CBC47D7257FC8C324AB7ED3E9F00B478EFDE41967BDB2923D6C8393291B0C022100BE6601EA37CA66EEB74F3E38C9B37CE44ECC99B6CF1D49D7A5271BBB573BF58A04&cmd=0000&res=00">
</div>

<button class="btn btn-primary" onclick="btnClicked()">Validate</button>
<p id="noArgsError" class="text-danger mt-3" style="display:none">Please provide a url</p>

<pre id="statusText" style="word-break: break-all; white-space: pre-wrap;"></pre>

<script type="text/javascript">
function log(data) {
console.log(data);
document
.getElementById('statusText')
.innerText += '\n' + data;
}

async function btnClicked() {
// Extract url from input
const url = document
.getElementById('url')
.value;

// Extract parameters from url
const urlParams = new URLSearchParams(url);
const pk2 = urlParams.get('pk2');
const rnd = urlParams.get('rnd');
const rndsig = urlParams.get('rndsig');
// Handle displaying/hiding the noArgsError message
if (!url) {
document
.getElementById('noArgsError')
.style
.display = 'block';
return;
} else {
document
.getElementById('noArgsError')
.style
.display = 'none';
}

// Convert a hex string to a byte array
function hexToBytes(hex) {
let bytes = [];
for (let c = 0; c < hex.length; c += 2)
bytes.push(parseInt(hex.substr(c, 2), 16));
return bytes;
}

const rnd_b = hexToBytes(rnd);
console.log({rnd_b});

let utf8Encode = new TextEncoder();
data = [
...utf8Encode.encode("\x19Attest counter pk2:\n"),
...rnd_b
];
console.log("data", data)
console.log("data0", data[0])
console.log("data5", data[5])
console.log("data len", data.length)

let sig = hexToBytes(rndsig);
sig = sig.slice(0, sig[1] + 2);
console.log("sig", sig)
console.log("sig[0]", sig[0])
console.log("sig[70]", sig[70])
console.log("sig len", sig.length)

const ec = new elliptic.ec('secp256k1');
console.log(ec)
const key = ec.keyFromPublic(pk2, "hex");
console.log(key.getPublic().encode("hex"))
console.log(pk2)
console.log(key.verify(data, sig));

/*
//Generate a Key Pair
const key = ec.keyFromPublic(pk2, "hex");
const publicKey = key.getPublic();
console.log({publicKey, pk2});
console.log({rndsig});
//console.log(key.verify(rnd, rndsig));
signature = {
r: "0x3D6CBC47D7257FC8C324AB7ED3E9F00B478EFDE41967BDB2923D6C8393291B0C",
s: "0x00BE6601EA37CA66EEB74F3E38C9B37CE44ECC99B6CF1D49D7A5271BBB573BF58A"
};
console.log(ec.verify(rnd, signature));
*/

/*var key = ec.genKeyPair();
var msgHash = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
var signature = key.sign(msgHash);
// Export DER encoded signature in Array
var derSign = signature.toDER();
console.log({derSign, signature})*/

/*
// Generate keys
var key = ec.genKeyPair();
// Sign the message's hash (input must be an array, or a hex-string)
var msgHash = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
var signature = key.sign(msgHash);
var derSign = signature.toDER();
console.log(signature)
console.log(derSign)
// Decode DER encoded signature
console.log(rndsig.slice(0, rndsig[1] + 2));
*/

//Generate a Key Pair
/*
const key = ec.keyFromPublic(pk2, "hex");
const publicKey = key.getPublic();
var m = signature.match(/([a-f\d]{64})/gi);
console.log({publicKey, pk2});
console.log({rndsig});
console.log(key.verify(rnd, rndsig));*/

/* WORKING EXAMPLE */
/*
const EC = elliptic.ec;
const ec = new EC('secp256k1');
//Generate a Key Pair
const key = ec.genKeyPair();
const publicKey = key.getPublic('hex');
const privateKey = key.getPrivate('hex');
//Generate a Signature
const message = "Hello, Ethereum!";
const msgHash = keccak256(btoa(message));
const signature = key.sign(msgHash, 'hex');
// Verify the signature
const isValid = ec.verify(msgHash, signature, publicKey, 'hex');
console.log(isValid);
*/

/*
var ec = new elliptic.ec('secp256k1');
// Generate keys
var key = ec.genKeyPair();
console.log(key)
console.log(key.getPublic("hex"))
// Sign the message's hash (input must be an array, or a hex-string)
var msgHash = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
var signature = key.sign(msgHash);
// Export DER encoded signature in Array
var derSign = signature.toDER();
// Verify signature
console.log(ec.verify(rnd, rndsig, pk2));*/

/*const rnd_b = hexToBinaryString(rnd);
console.log({ rnd_b });
let utf8Encode = new TextEncoder();
let utf8Decode = new TextDecoder();
data = utf8Encode.encode("\x19Attest counter pk2:\n" + rnd_b);
console.log({data})
console.log({data: utf8Decode.decode(data)})
let sig = hexToBinaryString(rndsig);
console.log({sig, test: ethers.utils.arrayify("0x"+rndsig)})
sig = sig.slice(0, sig[1] + 2);
console.log({sig})
console.log({pk2, test: hexToBinaryString(pk2)})
const pk2Bytes = ethers.utils.arrayify("0x"+pk2);
console.log({pk2Bytes})
const vk = new elliptic.ec('secp256k1').keyFromPublic(pk2, 'hex');
console.log("vk", vk);
const isValid = vk.verify(data, { r: sig.slice(0, 32), s: sig.slice(32, 64) });
console.log({isValid})*/

/*
function unhexlify(hexString) {
if (hexString.length % 2 !== 0) {
throw new Error('Invalid hex string');
}
const bytes = new Uint8Array(hexString.length / 2);
for (let i = 0; i < hexString.length; i += 2) {
bytes[i / 2] = parseInt(hexString.substr(i, 2), 16);
}
return bytes;
}
const rnd_b = unhexlify(rnd);
console.log({rnd, rnd_b})
*/

/*
def validate_rndsig(pk2, rnd, rndsig):
rnd_b = binascii.unhexlify(rnd)
data = b'\x19Attest counter pk2:\n' + rnd_b
sig = binascii.unhexlify(rndsig)
sig = sig[0:sig[1] + 2]
vk = VerifyingKey.from_string(binascii.unhexlify(pk2), curve=SECP256k1)
vk.verify(sig, data, sigdecode=sigdecode_der, hashfunc=sha256)
return struct.unpack(">I", rnd_b[0:4])[0]
if __name__ == "__main__":
PK2 = '0463D44E9708131505F8E8C5917DF96919624173EEF726DF3F0569865CE83BC9CD9A018879E56C2FF8DC12531A354A6E669714871D0A5F2B5D63E100E98F930DA5'
RND = '00000001FBAD9E01AA882F8669123390768FC8AF11916589DF638787A2C2700A'
RNDSIG = '304502203D6CBC47D7257FC8C324AB7ED3E9F00B478EFDE41967BDB2923D6C8393291B0C022100BE6601EA37CA66EEB74F3E38C9B37CE44ECC99B6CF1D49D7A5271BBB573BF58A04'
print('Validated OK, counter value:', validate_rndsig(PK2, RND, RNDSIG))
*/

function validateRndSig(pk2, rnd, rndsig) {
const rnd_b = ethers
.utils
.arrayify("0x" + rnd);
console.log("rnd_b", rnd_b);

const data = ethers
.utils
.concat([
ethers
.utils
.toUtf8Bytes("\x19Attest counter pk2:\n"),
rnd_b
]);
console.log("data", data);
const sig = ethers
.utils
.arrayify("0x" + rndsig)
.slice(0, ethers.utils.arrayify("0x" + rndsig)[1] + 2);
console.log("sig", sig);

const vk = new elliptic
.ec('secp256k1')
.keyFromPublic("04" + pk2, 'hex');
console.log("vk", vk);
const isValid = vk.verify(data, {
r: sig.slice(0, 32),
s: sig.slice(32, 64)
});
if (!isValid) {
throw new Error("Signature verification failed");
}

return new DataView(rnd_b.buffer).getUint32(0, false);
}

/*const PK2 = '0463D44E9708131505F8E8C5917DF96919624173EEF726DF3F0569865CE83BC9CD9A018879E56C2FF8DC12531A354A6E669714871D0A5F2B5D63E100E98F930DA5';
const RND = '00000001FBAD9E01AA882F8669123390768FC8AF11916589DF638787A2C2700A';
const RNDSIG = '304502203D6CBC47D7257FC8C324AB7ED3E9F00B478EFDE41967BDB2923D6C8393291B0C022100BE6601EA37CA66EEB74F3E38C9B37CE44ECC99B6CF1D49D7A5271BBB573BF58A04';
console.log("PK2", PK2);
console.log("RND", RND);
console.log("RNDSIG", RNDSIG);
console.log("\n\n");
console.log('Validated OK, counter value:', validateRndSig(PK2, RND, RNDSIG));*/

}

function hexToBinaryString(hexString) {
if (hexString.length % 2 !== 0) {
throw new Error('Invalid hex string');
}
let binaryString = '';
for (let i = 0; i < hexString.length; i += 2) {
const byte = parseInt(hexString.substr(i, 2, 16));
binaryString += String.fromCharCode(byte);
}
return binaryString;
}
</script>
</div>
</body>
</html>

0 comments on commit 32dd751

Please sign in to comment.