Replace Base 64 buggy conversion functions with `uint8arrays`

This commit is contained in:
Franck Royer 2022-03-25 11:02:40 +11:00
parent a67df28ae8
commit d0dea3884b
No known key found for this signature in database
GPG Key ID: A82ED75A8DFC50A4
5 changed files with 20 additions and 56 deletions

View File

@ -11,6 +11,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Examples: Add Relay JavaScript example.
### Fixed
- Replace Base 64 buggy conversion functions with `uint8arrays`.
## [0.19.2] - 2022-03-21
### Fixed

View File

@ -2,10 +2,11 @@ import assert from "assert";
import * as base32 from "hi-base32";
import { ecdsaVerify } from "secp256k1";
import { fromString } from "uint8arrays/from-string";
import { ENR } from "../enr";
import { utf8ToBytes } from "../utf8";
import { base64ToBytes, keccak256Buf } from "../utils";
import { keccak256Buf } from "../utils";
export type ENRRootValues = {
eRoot: string;
@ -43,7 +44,10 @@ export class ENRTree {
// (Trailing recovery bit must be trimmed to pass `ecdsaVerify` method)
const signedComponent = root.split(" sig")[0];
const signedComponentBuffer = utf8ToBytes(signedComponent);
const signatureBuffer = base64ToBytes(rootValues.signature).slice(0, 64);
const signatureBuffer = fromString(rootValues.signature, "base64url").slice(
0,
64
);
const isVerified = ecdsaVerify(
signatureBuffer,

View File

@ -29,7 +29,7 @@ describe("ENR", function () {
"/onion3/vww6ybal4bd7szmgncyruucpgfkqahzddi37ktceo3ah7ngmcopnpyyd:1234/wss"
),
];
const txt = await enr.encodeTxt(keypair.privateKey);
const txt = enr.encodeTxt(keypair.privateKey);
const enr2 = ENR.decodeTxt(txt);
if (!enr.signature) throw "enr.signature is undefined";
@ -102,7 +102,7 @@ describe("ENR", function () {
enr.setLocationMultiaddr(new Multiaddr("/ip4/18.223.219.100/udp/9000"));
enr.set("id", new Uint8Array([0]));
const txt = await enr.encodeTxt(keypair.privateKey);
const txt = enr.encodeTxt(keypair.privateKey);
ENR.decodeTxt(txt);
assert.fail("Expect error here");
@ -203,7 +203,7 @@ describe("ENR", function () {
expect(decoded).to.deep.equal(record);
});
it("should encode/decode to text encoding", async () => {
it("should encode/decode to text encoding", () => {
// spec enr https://eips.ethereum.org/EIPS/eip-778
const testTxt =
"enr:-IS4QHCYrYZbAKWCBRlAy5zzaDZXJBGkcnh4MHcBFZntXNFrdvJjX04jRzjzCBOonrkTfj499SZuOh8R33Ls8RRcy5wBgmlkgnY0gmlwhH8AAAGJc2VjcDI1NmsxoQPKY0yuDUmstAHYpMa2_oxVtw0RW_QAdpzBQA8yWM0xOIN1ZHCCdl8";
@ -211,7 +211,7 @@ describe("ENR", function () {
expect(decoded.udp).to.be.equal(30303);
expect(decoded.ip).to.be.equal("127.0.0.1");
expect(decoded).to.deep.equal(record);
const recordTxt = await record.encodeTxt(privateKey);
const recordTxt = record.encodeTxt(privateKey);
expect(recordTxt).to.equal(testTxt);
});
});

View File

@ -5,10 +5,12 @@ import { Multiaddr, protocols } from "multiaddr";
// @ts-ignore: No types available
import muConvert from "multiaddr/src/convert";
import PeerId from "peer-id";
import { fromString } from "uint8arrays/from-string";
import { toString } from "uint8arrays/to-string";
import { encode as varintEncode } from "varint";
import { bytesToUtf8, utf8ToBytes } from "../utf8";
import { base64ToBytes, bytesToBase64, bytesToHex, hexToBytes } from "../utils";
import { bytesToHex, hexToBytes } from "../utils";
import { ERR_INVALID_ID, ERR_NO_SIGNATURE, MAX_RECORD_SIZE } from "./constants";
import {
@ -107,7 +109,7 @@ export class ENR extends Map<ENRKey, ENRValue> {
`"string encoded ENR must start with '${this.RECORD_PREFIX}'`
);
}
return ENR.decode(base64ToBytes(encoded.slice(4)));
return ENR.decode(fromString(encoded.slice(4), "base64url"));
}
set(k: ENRKey, v: ENRValue): this {
@ -465,7 +467,7 @@ export class ENR extends Map<ENRKey, ENRValue> {
return encoded;
}
async encodeTxt(privateKey?: Uint8Array): Promise<string> {
return ENR.RECORD_PREFIX + (await bytesToBase64(this.encode(privateKey)));
encodeTxt(privateKey?: Uint8Array): string {
return ENR.RECORD_PREFIX + toString(this.encode(privateKey), "base64url");
}
}

View File

@ -81,49 +81,3 @@ export function equalByteArrays(
export function keccak256Buf(message: Message): Uint8Array {
return new Uint8Array(keccak256.arrayBuffer(message));
}
/**
* Convert base64 string to byte array.
*/
export function base64ToBytes(base64: string): Uint8Array {
const e = new Map<string, number>();
const len = base64.length;
const res = [];
const A = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
for (let i = 0; i < 64; i++) {
e.set(A.charAt(i), i);
}
e.set("+", 62);
e.set("/", 63);
let b = 0,
l = 0,
a;
for (let i = 0; i < len; i++) {
const c = e.get(base64.charAt(i));
if (c === undefined)
throw new Error(`Invalid base64 character ${base64.charAt(i)}`);
b = (b << 6) + c;
l += 6;
while (l >= 8) {
((a = (b >>> (l -= 8)) & 0xff) || i < len - 2) && res.push(a);
}
}
return new Uint8Array(res);
}
/**
* Convert byte array to base64 string.
*/
export async function bytesToBase64(bytes: Uint8Array): Promise<string> {
const base64url: string = await new Promise((r) => {
const reader = new window.FileReader();
reader.onload = (): void => r(reader.result as string);
reader.readAsDataURL(new Blob([bytes]));
});
const base64 = base64url.split(",", 2)[1];
// We want URL and Filename Safe base64: https://datatracker.ietf.org/doc/html/rfc4648#section-5
// Without trailing padding
return base64.replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
}