Skip to content

Commit

Permalink
Changed the proof value encoding
Browse files Browse the repository at this point in the history
  • Loading branch information
iherman committed Sep 11, 2024
1 parent 877a0d7 commit f59c423
Show file tree
Hide file tree
Showing 13 changed files with 570 additions and 102 deletions.
52 changes: 6 additions & 46 deletions dist/lib/crypto_utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
exports.generateKey = exports.cryptosuiteId = exports.verify = exports.sign = exports.jwkToCrypto = void 0;
const types = require("./types");
const types_1 = require("./types");
const base58 = require("./encodings/base58/index");
/***********************************************************************************
*
* JWK vs. WebCrypto API mappings
Expand Down Expand Up @@ -105,56 +106,13 @@ function algorithmDataCR(report, key) {
* Utilities for ArrayBuffer vs. string representations
*
***********************************************************************************/
/*
* These two came from perplexity, hopefully it is correct...
*/
const base64ToUrl = (base64String) => {
return base64String.replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, '');
};
const urlToBase64 = (base64Url) => {
return base64Url.replace(/-/g, '+').replace(/_/g, '/');
};
/**
* Text to array buffer, needed for crypto operations
* @param text
*/
function textToArrayBuffer(text) {
return (new TextEncoder()).encode(text).buffer;
}
/**
* Convert an array buffer to a base64url value.
*
* (Created with the help of chatgpt...)
*
* @param arrayBuffer
* @returns
*/
function arrayBufferToBase64Url(arrayBuffer) {
const bytes = new Uint8Array(arrayBuffer);
let binary = "";
for (let i = 0; i < bytes.length; i++) {
binary += String.fromCharCode(bytes[i]);
}
const base64String = btoa(binary);
return base64ToUrl(base64String);
}
/**
* Convert a base64url value to an array buffer
*
* (Created with the help of chatgpt...)
*
* @param url
* @returns
*/
function base64UrlToArrayBuffer(url) {
const base64string = urlToBase64(url);
const binary = atob(base64string);
const byteArray = new Uint8Array(binary.length);
for (let i = 0; i < binary.length; i++) {
byteArray[i] = binary.charCodeAt(i);
}
return byteArray.buffer;
}
/***********************************************************************************
*
* The externally visible API entries
Expand Down Expand Up @@ -198,7 +156,8 @@ async function sign(report, message, privateKey) {
try {
const rawSignature = await crypto.subtle.sign(algorithm, privateKey, rawMessage);
// Turn the the signature into Base64URL, and then into multicode
return `u${arrayBufferToBase64Url(rawSignature)}`;
return `z${base58.encode(new Uint8Array(rawSignature))}`;
// return `u${arrayBufferToBase64Url(rawSignature)}`;
}
catch (e) {
report.errors.push(new types.Proof_Generation_Error(e.message));
Expand All @@ -220,11 +179,12 @@ exports.sign = sign;
*/
async function verify(report, message, signature, publicKey) {
const rawMessage = textToArrayBuffer(message);
if (signature.length === 0 || signature[0] !== 'u') {
if (signature.length === 0 || signature[0] !== 'z') {
report.errors.push(new types.Proof_Verification_Error(`Signature is of an incorrect format (${signature})`));
return false;
}
const rawSignature = base64UrlToArrayBuffer(signature.slice(1));
const rawSignature = base58.decode(signature.slice(1));
// const rawSignature: ArrayBuffer = base64UrlToArrayBuffer(signature.slice(1));
// get the algorithm details
const algorithm = algorithmDataCR(report, publicKey);
if (algorithm === null) {
Expand Down
21 changes: 21 additions & 0 deletions dist/lib/encodings/base58/baseN.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/**
* BaseN-encodes a Uint8Array using the given alphabet.
*
* @param {Uint8Array} input - The bytes to encode in a Uint8Array.
* @param {string} alphabet - The alphabet to use for encoding.
* @param {number} maxline - The maximum number of encoded characters per line
* to use, defaults to none.
*
* @returns {string} The baseN-encoded output string.
*/
export function encode(input: Uint8Array, alphabet: string, maxline: number): string;
/**
* Decodes a baseN-encoded (using the given alphabet) string to a
* Uint8Array.
*
* @param {string} input - The baseN-encoded input string.
* @param {string} alphabet - The alphabet to use for decoding.
*
* @returns {Uint8Array} The decoded bytes in a Uint8Array.
*/
export function decode(input: string, alphabet: string): Uint8Array;
145 changes: 145 additions & 0 deletions dist/lib/encodings/base58/baseN.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.decode = exports.encode = void 0;
/**
* Base-N/Base-X encoding/decoding functions.
*
* Original implementation from base-x:
* https://github.com/cryptocoinjs/base-x
*
* Which is MIT licensed:
*
* The MIT License (MIT)
*
* Copyright base-x contributors (c) 2016
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
// baseN alphabet indexes
const _reverseAlphabets = {};
/**
* BaseN-encodes a Uint8Array using the given alphabet.
*
* @param {Uint8Array} input - The bytes to encode in a Uint8Array.
* @param {string} alphabet - The alphabet to use for encoding.
* @param {number} maxline - The maximum number of encoded characters per line
* to use, defaults to none.
*
* @returns {string} The baseN-encoded output string.
*/
function encode(input, alphabet, maxline) {
if (!(input instanceof Uint8Array)) {
throw new TypeError('"input" must be a Uint8Array.');
}
if (typeof alphabet !== 'string') {
throw new TypeError('"alphabet" must be a string.');
}
if (maxline !== undefined && typeof maxline !== 'number') {
throw new TypeError('"maxline" must be a number.');
}
if (input.length === 0) {
return '';
}
let output = '';
let i = 0;
const base = alphabet.length;
const first = alphabet.charAt(0);
const digits = [0];
for (i = 0; i < input.length; ++i) {
let carry = input[i];
for (let j = 0; j < digits.length; ++j) {
carry += digits[j] << 8;
digits[j] = carry % base;
carry = (carry / base) | 0;
}
while (carry > 0) {
digits.push(carry % base);
carry = (carry / base) | 0;
}
}
// deal with leading zeros
for (i = 0; input[i] === 0 && i < input.length - 1; ++i) {
output += first;
}
// convert digits to a string
for (i = digits.length - 1; i >= 0; --i) {
output += alphabet[digits[i]];
}
if (maxline) {
const regex = new RegExp('.{1,' + maxline + '}', 'g');
output = output.match(regex).join('\r\n');
}
return output;
}
exports.encode = encode;
/**
* Decodes a baseN-encoded (using the given alphabet) string to a
* Uint8Array.
*
* @param {string} input - The baseN-encoded input string.
* @param {string} alphabet - The alphabet to use for decoding.
*
* @returns {Uint8Array} The decoded bytes in a Uint8Array.
*/
function decode(input, alphabet) {
if (typeof input !== 'string') {
throw new TypeError('"input" must be a string.');
}
if (typeof alphabet !== 'string') {
throw new TypeError('"alphabet" must be a string.');
}
if (input.length === 0) {
return new Uint8Array();
}
let table = _reverseAlphabets[alphabet];
if (!table) {
// compute reverse alphabet
table = _reverseAlphabets[alphabet] = [];
for (let i = 0; i < alphabet.length; ++i) {
table[alphabet.charCodeAt(i)] = i;
}
}
// remove whitespace characters
input = input.replace(/\s/g, '');
const base = alphabet.length;
const first = alphabet.charAt(0);
const bytes = [0];
for (let i = 0; i < input.length; i++) {
const value = table[input.charCodeAt(i)];
if (value === undefined) {
return;
}
let carry = value;
for (let j = 0; j < bytes.length; ++j) {
carry += bytes[j] * base;
bytes[j] = carry & 0xff;
carry >>= 8;
}
while (carry > 0) {
bytes.push(carry & 0xff);
carry >>= 8;
}
}
// deal with leading zeros
for (let k = 0; input[k] === first && k < input.length - 1; ++k) {
bytes.push(0);
}
return new Uint8Array(bytes.reverse());
}
exports.decode = decode;
16 changes: 16 additions & 0 deletions dist/lib/encodings/base58/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/**
* Encoder function for base58url, needed for the Multikey encoding
*
* @param {*} input
* @param {*} maxline
* @returns
*/
export function encode(input: any, maxline: any): string;
/**
* Encoder function for base58url, needed for the Multikey encoding
*
* @param {*} input
* @param {*} maxline
* @returns
*/
export function decode(input: any): Uint8Array;
34 changes: 34 additions & 0 deletions dist/lib/encodings/base58/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.decode = exports.encode = void 0;
/**
* Base58url functions. This code
*
*
* Copyright (c) 2019-2022 Digital Bazaar, Inc. All rights reserved.
*/
const baseN_js_1 = require("./baseN.js");
// base58 characters (Bitcoin alphabet)
const alphabet = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz';
/**
* Encoder function for base58url, needed for the Multikey encoding
*
* @param {*} input
* @param {*} maxline
* @returns
*/
function encode(input, maxline) {
return (0, baseN_js_1.encode)(input, alphabet, maxline);
}
exports.encode = encode;
/**
* Encoder function for base58url, needed for the Multikey encoding
*
* @param {*} input
* @param {*} maxline
* @returns
*/
function decode(input) {
return (0, baseN_js_1.decode)(input, alphabet);
}
exports.decode = decode;
23 changes: 23 additions & 0 deletions dist/lib/encodings/base64.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/**
* Base 64 encoding/decoding
*
* @module
*/
/**
* Convert an array buffer to base64url value.
*
* (Created with the help of perplexity.io...)
*
* @param arrayBuffer
* @returns
*/
export declare function encode(bytes: Uint8Array): string;
/**
* Convert a base64url value to Uint8Array
*
* (Created with the help of perplexity.io...)
*
* @param string
* @returns
*/
export declare function decode(url: string): Uint8Array;
52 changes: 52 additions & 0 deletions dist/lib/encodings/base64.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
"use strict";
/**
* Base 64 encoding/decoding
*
* @module
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.decode = exports.encode = void 0;
/*
* These two came from perplexity.io, hopefully it is correct...
*/
const base64ToUrl = (base64String) => {
return base64String.replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, '');
};
const urlToBase64 = (base64Url) => {
return base64Url.replace(/-/g, '+').replace(/_/g, '/');
};
/**
* Convert an array buffer to base64url value.
*
* (Created with the help of perplexity.io...)
*
* @param arrayBuffer
* @returns
*/
function encode(bytes) {
let binary = "";
for (let i = 0; i < bytes.length; i++) {
binary += String.fromCharCode(bytes[i]);
}
const base64String = btoa(binary);
return base64ToUrl(base64String);
}
exports.encode = encode;
/**
* Convert a base64url value to Uint8Array
*
* (Created with the help of perplexity.io...)
*
* @param string
* @returns
*/
function decode(url) {
const base64string = urlToBase64(url);
const binary = atob(base64string);
const byteArray = new Uint8Array(binary.length);
for (let i = 0; i < binary.length; i++) {
byteArray[i] = binary.charCodeAt(i);
}
return byteArray;
}
exports.decode = decode;
Loading

0 comments on commit f59c423

Please sign in to comment.