Only allow padding characters in base64 strings (#1842)

* Only allow padding characters in base64 strings

* Explicit padding sequence error
This commit is contained in:
Jaco
2023-06-06 08:31:44 +03:00
committed by GitHub
parent 04b6df9ac5
commit eea99656ad
5 changed files with 60 additions and 8 deletions
+7
View File
@@ -1,5 +1,12 @@
# CHANGELOG
## master
Changes:
- Only allow padding characters in base64 strings
## 12.2.2 Jun 4, 2023
Changes:
+13 -7
View File
@@ -19,6 +19,7 @@ interface Config {
ipfs?: string;
regex?: RegExp;
type: string;
withPadding?: boolean;
}
type DecodeFn = (value: string, ipfsCompat?: boolean) => Uint8Array;
@@ -63,7 +64,7 @@ export function createIs (validate: ValidateFn): ValidateFn {
}
/** @internal */
export function createValidate ({ chars, ipfs, type }: Config): ValidateFn {
export function createValidate ({ chars, ipfs, type, withPadding }: Config): ValidateFn {
return (value?: unknown, ipfsCompat?: boolean): value is string => {
if (typeof value !== 'string') {
throw new Error(`Expected ${type} string input`);
@@ -72,12 +73,17 @@ export function createValidate ({ chars, ipfs, type }: Config): ValidateFn {
}
for (let i = (ipfsCompat ? 1 : 0), count = value.length; i < count; i++) {
if (!(chars.includes(value[i]) || (
value[i] === '=' && (
(i === value.length - 1) ||
!chars.includes(value[i + 1])
)
))) {
if (chars.includes(value[i])) {
// all ok, character found
} else if (withPadding && value[i] === '=') {
if (i === count - 1) {
// last character, everything ok
} else if (value[i + 1] === '=') {
// next one is also padding, sequence ok
} else {
throw new Error(`Invalid ${type} padding sequence "${value[i]}${value[i + 1]}" at index ${i}`);
}
} else {
throw new Error(`Invalid ${type} character "${value[i]}" (0x${value.charCodeAt(i).toString(16)}) at index ${i}`);
}
}
@@ -0,0 +1,20 @@
// Copyright 2017-2023 @polkadot/util-crypto authors & contributors
// SPDX-License-Identifier: Apache-2.0
/// <reference types="@polkadot/dev-test/globals.d.ts" />
import { base58Validate } from './index.js';
describe('base58Validate', (): void => {
it('validates encoded', (): void => {
expect(
base58Validate('a1UbyspTdnyZXLUQaQbciCxrCWWxz24kgSwGXSQnkbs', false)
).toEqual(true);
});
it('fails on string with extra padding', (): void => {
expect(
() => base58Validate('a1UbyspTdnyZXLUQaQbciCxrCWWxz24kgSwGXSQnkbs=', false)
).toThrow(/Invalid base58 character "="/);
});
});
+2 -1
View File
@@ -8,7 +8,8 @@ import { createDecode, createEncode, createIs, createValidate } from '../base32/
const config = {
chars: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/',
coder: base64,
type: 'base64'
type: 'base64',
withPadding: true
};
/**
@@ -11,4 +11,22 @@ describe('base64Validate', (): void => {
() => base64Validate('aGVsbG8gd29ybGQg0J/RgNC40LLQtd^GC0YHRgtCy0YPRjiDQvNC4IOS9oOWlvQ==')
).toThrow(/Invalid base64 character "\^" \(0x5e\) at index 30/);
});
it('validates with one extra padding character', (): void => {
expect(
base64Validate('bGlnaHQgd28=')
).toEqual(true);
});
it('validates with two extra padding characters', (): void => {
expect(
base64Validate('bGlnaHQgdw==')
).toEqual(true);
});
it('validates misplaced padding characters', (): void => {
expect(
() => base64Validate('bGlnaHQgdw=g=')
).toThrow(/Invalid base64 padding sequence "=g"/);
});
});