mirror of
https://github.com/openpgpjs/openpgpjs.git
synced 2025-11-24 14:35:51 +00:00
Refactor: s2k module to Typescrip
This commit is contained in:
parent
e92b44bc84
commit
48bd1a06f0
@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
import * as stream from '@openpgp/web-stream-tools';
|
import * as stream from '@openpgp/web-stream-tools';
|
||||||
import { armor, unarmor } from './encoding/armor';
|
import { armor, unarmor } from './encoding/armor';
|
||||||
import { Argon2OutOfMemoryError } from './type/s2k';
|
import { Argon2OutOfMemoryError } from './type/s2k/index.ts';
|
||||||
import defaultConfig from './config';
|
import defaultConfig from './config';
|
||||||
import crypto from './crypto';
|
import crypto from './crypto';
|
||||||
import enums from './enums';
|
import enums from './enums';
|
||||||
|
|||||||
@ -16,7 +16,7 @@
|
|||||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
import PublicKeyPacket from './public_key';
|
import PublicKeyPacket from './public_key';
|
||||||
import { newS2KFromConfig, newS2KFromType } from '../type/s2k';
|
import { newS2KFromConfig, newS2KFromType } from '../type/s2k/index.ts';
|
||||||
import crypto from '../crypto';
|
import crypto from '../crypto';
|
||||||
import enums from '../enums';
|
import enums from '../enums';
|
||||||
import util from '../util';
|
import util from '../util';
|
||||||
|
|||||||
@ -15,7 +15,7 @@
|
|||||||
// License along with this library; if not, write to the Free Software
|
// License along with this library; if not, write to the Free Software
|
||||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
import { newS2KFromConfig, newS2KFromType } from '../type/s2k';
|
import { newS2KFromConfig, newS2KFromType } from '../type/s2k/index.ts';
|
||||||
import defaultConfig from '../config';
|
import defaultConfig from '../config';
|
||||||
import crypto from '../crypto';
|
import crypto from '../crypto';
|
||||||
import computeHKDF from '../crypto/hkdf';
|
import computeHKDF from '../crypto/hkdf';
|
||||||
|
|||||||
@ -8,7 +8,7 @@ const ARGON2_VERSION = 0x13;
|
|||||||
const ARGON2_SALT_SIZE = 16;
|
const ARGON2_SALT_SIZE = 16;
|
||||||
|
|
||||||
export class Argon2OutOfMemoryError extends Error {
|
export class Argon2OutOfMemoryError extends Error {
|
||||||
constructor(...params) {
|
constructor(...params: string[]) {
|
||||||
super(...params);
|
super(...params);
|
||||||
|
|
||||||
if (Error.captureStackTrace) {
|
if (Error.captureStackTrace) {
|
||||||
@ -20,16 +20,22 @@ export class Argon2OutOfMemoryError extends Error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// cache argon wasm module
|
// cache argon wasm module
|
||||||
let loadArgonWasmModule;
|
let loadArgonWasmModule: Function;
|
||||||
let argon2Promise;
|
let argon2Promise: Promise<Function>;
|
||||||
// reload wasm module above this treshold, to deallocated used memory
|
// reload wasm module above this treshold, to deallocated used memory
|
||||||
const ARGON2_WASM_MEMORY_THRESHOLD_RELOAD = 2 << 19;
|
const ARGON2_WASM_MEMORY_THRESHOLD_RELOAD = 2 << 19;
|
||||||
|
|
||||||
class Argon2S2K {
|
class Argon2S2K {
|
||||||
|
type: string;
|
||||||
|
salt: Uint8Array | null;
|
||||||
|
t: number;
|
||||||
|
p: number;
|
||||||
|
encodedM: number;
|
||||||
/**
|
/**
|
||||||
* @param {Object} [config] - Full configuration, defaults to openpgp.config
|
* @param {Object} [config] - Full configuration, defaults to openpgp.config
|
||||||
*/
|
*/
|
||||||
constructor(config = defaultConfig) {
|
constructor(config = defaultConfig) {
|
||||||
|
|
||||||
const { passes, parallelism, memoryExponent } = config.s2kArgon2Params;
|
const { passes, parallelism, memoryExponent } = config.s2kArgon2Params;
|
||||||
|
|
||||||
this.type = 'argon2';
|
this.type = 'argon2';
|
||||||
@ -52,7 +58,7 @@ class Argon2S2K {
|
|||||||
* @param {Uint8Array} bytes - Payload of argon2 string-to-key specifier
|
* @param {Uint8Array} bytes - Payload of argon2 string-to-key specifier
|
||||||
* @returns {Integer} Actual length of the object.
|
* @returns {Integer} Actual length of the object.
|
||||||
*/
|
*/
|
||||||
read(bytes) {
|
read(bytes: Uint8Array) {
|
||||||
let i = 0;
|
let i = 0;
|
||||||
|
|
||||||
this.salt = bytes.subarray(i, i + 16);
|
this.salt = bytes.subarray(i, i + 16);
|
||||||
@ -69,7 +75,7 @@ class Argon2S2K {
|
|||||||
* Serializes s2k information
|
* Serializes s2k information
|
||||||
* @returns {Uint8Array} Binary representation of s2k.
|
* @returns {Uint8Array} Binary representation of s2k.
|
||||||
*/
|
*/
|
||||||
write() {
|
write(): Uint8Array {
|
||||||
const arr = [
|
const arr = [
|
||||||
new Uint8Array([enums.write(enums.s2k, this.type)]),
|
new Uint8Array([enums.write(enums.s2k, this.type)]),
|
||||||
this.salt,
|
this.salt,
|
||||||
@ -87,7 +93,7 @@ class Argon2S2K {
|
|||||||
* @throws {Argon2OutOfMemoryError|Errors}
|
* @throws {Argon2OutOfMemoryError|Errors}
|
||||||
* @async
|
* @async
|
||||||
*/
|
*/
|
||||||
async produceKey(passphrase, keySize) {
|
async produceKey(passphrase: string, keySize: number): Promise<Uint8Array> {
|
||||||
const decodedM = 2 << (this.encodedM - 1);
|
const decodedM = 2 << (this.encodedM - 1);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -120,7 +126,7 @@ class Argon2S2K {
|
|||||||
}
|
}
|
||||||
return hash;
|
return hash;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e.message && (
|
if (e instanceof Error && e.message && (
|
||||||
e.message.includes('Unable to grow instance memory') || // Chrome
|
e.message.includes('Unable to grow instance memory') || // Chrome
|
||||||
e.message.includes('failed to grow memory') || // Firefox
|
e.message.includes('failed to grow memory') || // Firefox
|
||||||
e.message.includes('WebAssembly.Memory.grow') || // Safari
|
e.message.includes('WebAssembly.Memory.grow') || // Safari
|
||||||
@ -34,10 +34,14 @@ import { UnsupportedError } from '../../packet/packet';
|
|||||||
import util from '../../util';
|
import util from '../../util';
|
||||||
|
|
||||||
class GenericS2K {
|
class GenericS2K {
|
||||||
|
algorithm: number;
|
||||||
|
type: string;
|
||||||
|
c: number;
|
||||||
|
salt: Uint8Array | null;
|
||||||
/**
|
/**
|
||||||
* @param {Object} [config] - Full configuration, defaults to openpgp.config
|
* @param {Object} [config] - Full configuration, defaults to openpgp.config
|
||||||
*/
|
*/
|
||||||
constructor(s2kType, config = defaultConfig) {
|
constructor(s2kType: number, config = defaultConfig) {
|
||||||
/**
|
/**
|
||||||
* Hash function identifier, or 0 for gnu-dummy keys
|
* Hash function identifier, or 0 for gnu-dummy keys
|
||||||
* @type {module:enums.hash | 0}
|
* @type {module:enums.hash | 0}
|
||||||
@ -76,7 +80,7 @@ class GenericS2K {
|
|||||||
* @param {Uint8Array} bytes - Payload of string-to-key specifier
|
* @param {Uint8Array} bytes - Payload of string-to-key specifier
|
||||||
* @returns {Integer} Actual length of the object.
|
* @returns {Integer} Actual length of the object.
|
||||||
*/
|
*/
|
||||||
read(bytes) {
|
read(bytes: Uint8Array): Number {
|
||||||
let i = 0;
|
let i = 0;
|
||||||
this.algorithm = bytes[i++];
|
this.algorithm = bytes[i++];
|
||||||
|
|
||||||
@ -123,7 +127,7 @@ class GenericS2K {
|
|||||||
* Serializes s2k information
|
* Serializes s2k information
|
||||||
* @returns {Uint8Array} Binary representation of s2k.
|
* @returns {Uint8Array} Binary representation of s2k.
|
||||||
*/
|
*/
|
||||||
write() {
|
write(): Uint8Array {
|
||||||
if (this.type === 'gnu-dummy') {
|
if (this.type === 'gnu-dummy') {
|
||||||
return new Uint8Array([101, 0, ...util.stringToUint8Array('GNU'), 1]);
|
return new Uint8Array([101, 0, ...util.stringToUint8Array('GNU'), 1]);
|
||||||
}
|
}
|
||||||
@ -133,10 +137,10 @@ class GenericS2K {
|
|||||||
case 'simple':
|
case 'simple':
|
||||||
break;
|
break;
|
||||||
case 'salted':
|
case 'salted':
|
||||||
arr.push(this.salt);
|
this.salt && arr.push(this.salt);
|
||||||
break;
|
break;
|
||||||
case 'iterated':
|
case 'iterated':
|
||||||
arr.push(this.salt);
|
this.salt &&arr.push(this.salt);
|
||||||
arr.push(new Uint8Array([this.c]));
|
arr.push(new Uint8Array([this.c]));
|
||||||
break;
|
break;
|
||||||
case 'gnu':
|
case 'gnu':
|
||||||
@ -156,8 +160,8 @@ class GenericS2K {
|
|||||||
* hashAlgorithm hash length
|
* hashAlgorithm hash length
|
||||||
* @async
|
* @async
|
||||||
*/
|
*/
|
||||||
async produceKey(passphrase, numBytes) {
|
async produceKey(passphrase: string, numBytes: number): Promise<Uint8Array> {
|
||||||
passphrase = util.encodeUTF8(passphrase);
|
const encodedPassphrase = util.encodeUTF8(passphrase);
|
||||||
|
|
||||||
const arr = [];
|
const arr = [];
|
||||||
let rlength = 0;
|
let rlength = 0;
|
||||||
@ -167,13 +171,13 @@ class GenericS2K {
|
|||||||
let toHash;
|
let toHash;
|
||||||
switch (this.type) {
|
switch (this.type) {
|
||||||
case 'simple':
|
case 'simple':
|
||||||
toHash = util.concatUint8Array([new Uint8Array(prefixlen), passphrase]);
|
toHash = util.concatUint8Array([new Uint8Array(prefixlen), encodedPassphrase]);
|
||||||
break;
|
break;
|
||||||
case 'salted':
|
case 'salted':
|
||||||
toHash = util.concatUint8Array([new Uint8Array(prefixlen), this.salt, passphrase]);
|
toHash = util.concatUint8Array([new Uint8Array(prefixlen), this.salt, encodedPassphrase]);
|
||||||
break;
|
break;
|
||||||
case 'iterated': {
|
case 'iterated': {
|
||||||
const data = util.concatUint8Array([this.salt, passphrase]);
|
const data = util.concatUint8Array([this.salt, encodedPassphrase]);
|
||||||
let datalen = data.length;
|
let datalen = data.length;
|
||||||
const count = Math.max(this.getCount(), datalen);
|
const count = Math.max(this.getCount(), datalen);
|
||||||
toHash = new Uint8Array(prefixlen + count);
|
toHash = new Uint8Array(prefixlen + count);
|
||||||
@ -13,7 +13,7 @@ const allowedS2KTypesForEncryption = new Set([enums.s2k.argon2, enums.s2k.iterat
|
|||||||
* @returns {Object} New s2k object
|
* @returns {Object} New s2k object
|
||||||
* @throws {Error} for unknown or unsupported types
|
* @throws {Error} for unknown or unsupported types
|
||||||
*/
|
*/
|
||||||
export function newS2KFromType(type, config = defaultConfig) {
|
export function newS2KFromType (type: number, config = defaultConfig): Argon2S2K | GenericS2K {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case enums.s2k.argon2:
|
case enums.s2k.argon2:
|
||||||
return new Argon2S2K(config);
|
return new Argon2S2K(config);
|
||||||
@ -33,7 +33,7 @@ export function newS2KFromType(type, config = defaultConfig) {
|
|||||||
* @returns {Object} New s2k object
|
* @returns {Object} New s2k object
|
||||||
* @throws {Error} for unknown or unsupported types
|
* @throws {Error} for unknown or unsupported types
|
||||||
*/
|
*/
|
||||||
export function newS2KFromConfig(config) {
|
export function newS2KFromConfig(config = defaultConfig) {
|
||||||
const { s2kType } = config;
|
const { s2kType } = config;
|
||||||
|
|
||||||
if (!allowedS2KTypesForEncryption.has(s2kType)) {
|
if (!allowedS2KTypesForEncryption.has(s2kType)) {
|
||||||
Loading…
x
Reference in New Issue
Block a user