Skip to content

Commit

Permalink
feat(utf8): use TextEncoder
Browse files Browse the repository at this point in the history
  • Loading branch information
clshortfuse committed Jul 16, 2023
1 parent 843ef2d commit 515df89
Show file tree
Hide file tree
Showing 6 changed files with 27 additions and 17 deletions.
4 changes: 2 additions & 2 deletions lib/jws.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { decodeBase64UrlAsArray, decodeBase64UrlAsString, encodeBase64UrlAsString } from '../utils/base64.js';
import { octetFromUtf8 } from '../utils/utf8.js';
import { uint8ArrayFromUtf8 } from '../utils/utf8.js';

import KeyStore from './KeyStore.js';
import { decodeProtectedHeader, encodePayload, encodeProtectedHeader } from './jose.js';
Expand Down Expand Up @@ -177,7 +177,7 @@ export async function validateSignature(encodedPayload, signatureObject, jwk) {
const verified = await KeyStore.default.verify(
jwk,
decodeBase64UrlAsArray(signature),
Uint8Array.from(octetFromUtf8(signingInput)),
uint8ArrayFromUtf8(signingInput),
);
if (verified) return;
} catch (e) { console.error(e); }
Expand Down
6 changes: 3 additions & 3 deletions test/lib/jws.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { createES256JWK, createES512JWK, createHS256JWK, createRS256JWK } from '../../lib/jwa.js';
import { decodeJSON, decodeJSONUnsafe, decodeString, decodeStringUnsafe, decodeUint8Array, decodeUint8ArrayUnsafe, signCompact, signObject, validate } from '../../lib/jws.js';
import { decodeBase64AsString, decodeBase64UrlAsArray, encodeBase64UrlAsString } from '../../utils/base64.js';
import { octetFromUtf8 } from '../../utils/utf8.js';
import { uint8ArrayFromUtf8 } from '../../utils/utf8.js';
import test from '../tester.js';

const RFC7515_APPENDIX_A_JWS = 'eyJ0eXAiOiJKV1QiLA0KICJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ.dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk';
Expand Down Expand Up @@ -344,7 +344,7 @@ test('CVE-2015-9235 - Replicate setup', async (t) => {
const header = { alg: 'HS256', typ: 'JWT' };
const payload = { loggedInAs: 'admin', iat: 1_422_779_638 };
const key = 'secretkey';
const hmacKey = new Uint8Array(octetFromUtf8(key));
const hmacKey = uint8ArrayFromUtf8(key);
const symmetricalJWK = createHS256JWK({ k: hmacKey });
const symmetricalJWS = await signCompact({
protected: header,
Expand All @@ -360,7 +360,7 @@ test('CVE-2015-9235 - Validation should fail if token specifies alg:none though
const header = { alg: 'none', typ: 'JWT' };
const payload = { loggedInAs: 'admin', iat: 1_422_779_638 };
const key = 'secretkey';
const hmacKey = new Uint8Array(octetFromUtf8(key));
const hmacKey = uint8ArrayFromUtf8(key);
const symmetricalJWK = createHS256JWK({ k: hmacKey });

// Will not allow conflict when signing
Expand Down
12 changes: 5 additions & 7 deletions utils/asn1/encoder.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/* eslint-disable no-bitwise */

import { decodeBase64AsArray } from '../base64.js';
import { octetFromUtf8 } from '../utf8.js';
import { uint8ArrayFromUtf8 } from '../utf8.js';

// https://letsencrypt.org/docs/a-warm-welcome-to-asn1-and-der/

Expand Down Expand Up @@ -178,17 +178,16 @@ export function encodeDER(tag, entry) {
*/
export function encodeUTF8String(utf8String) {
// ASCII to Hex is the same as UTF8 to HEX (no check)
const entry = [...octetFromUtf8(utf8String)];
return encodeDER(ASN_TAG.UTF8_STRING, entry);
return encodeDER(ASN_TAG.UTF8_STRING, uint8ArrayFromUtf8(utf8String));
}

/**
* @param {string} ia5String
* @return {number[]}
* @return {ArrayLike<number>&Iterable<number>}
*/
export function writeIA5String(ia5String) {
// First 128 characters of ASCII (no check)
return [...octetFromUtf8(ia5String)];
return uint8ArrayFromUtf8(ia5String);
}

/**
Expand Down Expand Up @@ -326,8 +325,7 @@ export function encodeBitString(data, length = data.length * 8) {
export function encodePrintableString(printableString) {
// ASCII to Hex is the same as UTF8 to HEX
// No checks here
const entry = [...octetFromUtf8(printableString)];
return encodeDER(ASN_TAG.PRINTABLE_STRING, entry);
return encodeDER(ASN_TAG.PRINTABLE_STRING, uint8ArrayFromUtf8(printableString));
}

/**
Expand Down
4 changes: 2 additions & 2 deletions utils/base64.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/* eslint-disable no-bitwise */
// https://datatracker.ietf.org/doc/html/rfc4648#section-4

import { octetFromUtf8 } from './utf8.js';
import { uint8ArrayFromUtf8 } from './utf8.js';

const BASE64_CHAR_62 = '+';
const BASE64_CHAR_63 = '/';
Expand Down Expand Up @@ -42,7 +42,7 @@ const BIT_MASK_8 = BIT_MASKS.get(8);
*/
function toIterableUint8(source) {
if (typeof source === 'string') {
return octetFromUtf8(source);
return uint8ArrayFromUtf8(source);
}
if (source instanceof Uint8Array) {
return source;
Expand Down
6 changes: 3 additions & 3 deletions utils/crypto.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

import { parseAlgorithmIdentifier } from '../lib/jwa.js';

import { octetFromUtf8 } from './utf8.js';
import { uint8ArrayFromUtf8 } from './utf8.js';

/** @type {Crypto} */
// eslint-disable-next-line unicorn/no-await-expression-member
Expand Down Expand Up @@ -31,7 +31,7 @@ export async function importJWK(jwk, algorithmIdentifier) {
* @return {Promise<ArrayBuffer>}
*/
export async function sign(algorithmIdentifier, key, data) {
const binary = typeof data === 'string' ? Uint8Array.from(octetFromUtf8(data)) : data;
const binary = typeof data === 'string' ? uint8ArrayFromUtf8(data) : data;
return await crypto.subtle.sign(algorithmIdentifier, key, binary);
}

Expand Down Expand Up @@ -72,6 +72,6 @@ export async function decrypt(algorithmIdentifier, key, data) {
* @return {Promise<ArrayBuffer>}
*/
export async function digest(algorithm, data) {
const binary = typeof data === 'string' ? Uint8Array.from(octetFromUtf8(data)) : data;
const binary = typeof data === 'string' ? uint8ArrayFromUtf8(data) : data;
return await crypto.subtle.digest(algorithm, binary);
}
12 changes: 12 additions & 0 deletions utils/utf8.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,15 @@ export function* octetFromUtf8(utf8) {
}
}
}

/** @type {TextEncoder} */
let textEncoder;

/**
* @param {string} utf8
* @return {Uint8Array}
*/
export function uint8ArrayFromUtf8(utf8) {
textEncoder ??= new TextEncoder();
return textEncoder.encode(utf8);
}

0 comments on commit 515df89

Please sign in to comment.