tslint -> eslint

This commit is contained in:
microshine 2020-03-13 14:06:53 +03:00
parent 2519880f2e
commit a2b9971e46
25 changed files with 1444 additions and 208 deletions

30
.eslintrc.json Normal file
View File

@ -0,0 +1,30 @@
{
"parser": "@typescript-eslint/parser",
"plugins": [
"@typescript-eslint"
],
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/eslint-recommended",
"plugin:@typescript-eslint/recommended",
"plugin:import/errors",
"plugin:import/warnings",
"plugin:import/typescript"
],
"rules": {
"@typescript-eslint/ban-ts-ignore": 0,
"@typescript-eslint/camelcase": 0,
"@typescript-eslint/explicit-function-return-type": 0,
"@typescript-eslint/interface-name-prefix": 0,
"@typescript-eslint/no-explicit-any": 0,
"@typescript-eslint/semi": 1,
"semi": "off",
"import/order": ["error", {
"groups": ["builtin", "external", "internal"],
"alphabetize": {
"order": "asc",
"caseInsensitive": true
}
}]
}
}

1389
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -18,8 +18,8 @@
"clear": "rimraf build/*",
"rebuild": "npm run clear && npm run build",
"build:module": "rollup -c",
"lint": "tslint -p .",
"lint:fix": "tslint --fix -p .",
"lint": "eslint . --ext .ts",
"lint:fix": "eslint --fix . --ext .ts",
"prepub": "npm run lint && npm run rebuild",
"pub": "npm version patch && npm publish",
"postpub": "git push && git push --tags origin master",
@ -47,18 +47,21 @@
"url": "https://github.com/PeculiarVentures/webcrypto/issues"
},
"homepage": "https://github.com/PeculiarVentures/webcrypto#readme",
"banner": "// Copyright (c) 2019, Peculiar Ventures, All rights reserved.",
"banner": "// Copyright (c) 2020, Peculiar Ventures, All rights reserved.",
"devDependencies": {
"@types/mocha": "^5.2.7",
"@types/node": "^12.12.29",
"@types/mocha": "^7.0.2",
"@types/node": "^12.12.30",
"@typescript-eslint/eslint-plugin": "^2.23.0",
"@typescript-eslint/parser": "^2.23.0",
"coveralls": "^3.0.9",
"mocha": "^6.2.2",
"eslint": "^6.8.0",
"eslint-plugin-import": "^2.20.1",
"mocha": "^7.1.0",
"nyc": "^14.1.1",
"rimraf": "^3.0.2",
"rollup": "^1.32.1",
"rollup-plugin-typescript2": "^0.25.3",
"rollup": "^2.0.6",
"rollup-plugin-typescript2": "^0.26.0",
"ts-node": "^8.6.2",
"tslint": "^5.20.1",
"typescript": "^3.8.3"
},
"dependencies": {

View File

@ -1,4 +1,4 @@
import { AsnIntegerConverter, AsnParser, AsnProp, AsnPropTypes, AsnSerializer, IAsnConverter } from "@peculiar/asn1-schema";
import { AsnIntegerConverter, AsnProp, AsnPropTypes, AsnSerializer } from "@peculiar/asn1-schema";
import { IJsonConvertible } from "@peculiar/json-schema";
import { Convert } from "pvtsutils";
import { EcPublicKey } from "./ec_public_key";

View File

@ -1,4 +1,4 @@
import { AsnIntegerArrayBufferConverter, AsnProp, AsnPropTypes, IAsnConverter } from "@peculiar/asn1-schema";
import { AsnProp, AsnPropTypes, IAsnConverter } from "@peculiar/asn1-schema";
// @ts-ignore
import * as asn1 from "asn1js";

View File

@ -7,7 +7,7 @@ export class CryptoKey extends core.CryptoKey {
public algorithm: KeyAlgorithm = { name: "" };
@JsonProp({ name: "ext", type: JsonPropTypes.Boolean, optional: true })
public extractable: boolean = false;
public extractable = false;
public type: KeyType = "secret";
@ -15,8 +15,8 @@ export class CryptoKey extends core.CryptoKey {
public usages: KeyUsage[] = [];
@JsonProp({ type: JsonPropTypes.String })
protected kty: string = "oct";
protected kty = "oct";
@JsonProp({ type: JsonPropTypes.String })
protected alg: string = "";
protected alg = "";
}

View File

@ -31,7 +31,7 @@ export class AesCbcProvider extends core.AesCbcProvider {
public async onImportKey(format: KeyFormat, keyData: JsonWebKey | ArrayBuffer, algorithm: Algorithm, extractable: boolean, keyUsages: KeyUsage[]): Promise<CryptoKey> {
return AesCrypto.importKey(format, keyData, { name: algorithm.name }, extractable, keyUsages);
}
public checkCryptoKey(key: CryptoKey, keyUsage?: KeyUsage) {
super.checkCryptoKey(key, keyUsage);
if (!(key instanceof AesCryptoKey)) {

View File

@ -34,22 +34,6 @@ function xor(a: Buffer, b: Buffer) {
return output;
}
function generateSubkeys(key: Buffer) {
const l = aes(key, zero);
let subkey1 = bitShiftLeft(l);
if (l[0] & 0x80) {
subkey1 = xor(subkey1, rb);
}
let subkey2 = bitShiftLeft(subkey1);
if (subkey1[0] & 0x80) {
subkey2 = xor(subkey2, rb);
}
return { subkey1, subkey2 };
}
function aes(key: Buffer, message: Buffer) {
const cipher = crypto.createCipheriv(`aes${key.length << 3}`, key, zero);
const result = cipher.update(message);
@ -57,38 +41,6 @@ function aes(key: Buffer, message: Buffer) {
return result;
}
function aesCmac(key: Buffer, message: Buffer) {
const subkeys = generateSubkeys(key);
let blockCount = Math.ceil(message.length / blockSize);
let lastBlockCompleteFlag: boolean;
let lastBlock: Buffer;
let lastBlockIndex: number;
if (blockCount === 0) {
blockCount = 1;
lastBlockCompleteFlag = false;
} else {
lastBlockCompleteFlag = (message.length % blockSize === 0);
}
lastBlockIndex = blockCount - 1;
if (lastBlockCompleteFlag) {
lastBlock = xor(getMessageBlock(message, lastBlockIndex), subkeys.subkey1);
} else {
lastBlock = xor(getPaddedMessageBlock(message, lastBlockIndex), subkeys.subkey2);
}
let x = zero;
let y;
for (let index = 0; index < lastBlockIndex; index++) {
y = xor(x, getMessageBlock(message, index));
x = aes(key, y);
}
y = xor(lastBlock, x);
return aes(key, y);
}
function getMessageBlock(message: Buffer, blockIndex: number) {
const block = new Buffer(blockSize);
const start = blockIndex * blockSize;
@ -111,6 +63,53 @@ function getPaddedMessageBlock(message: Buffer, blockIndex: number) {
return block;
}
function generateSubkeys(key: Buffer) {
const l = aes(key, zero);
let subkey1 = bitShiftLeft(l);
if (l[0] & 0x80) {
subkey1 = xor(subkey1, rb);
}
let subkey2 = bitShiftLeft(subkey1);
if (subkey1[0] & 0x80) {
subkey2 = xor(subkey2, rb);
}
return { subkey1, subkey2 };
}
function aesCmac(key: Buffer, message: Buffer) {
const subkeys = generateSubkeys(key);
let blockCount = Math.ceil(message.length / blockSize);
let lastBlockCompleteFlag: boolean;
let lastBlock: Buffer;
if (blockCount === 0) {
blockCount = 1;
lastBlockCompleteFlag = false;
} else {
lastBlockCompleteFlag = (message.length % blockSize === 0);
}
const lastBlockIndex = blockCount - 1;
if (lastBlockCompleteFlag) {
lastBlock = xor(getMessageBlock(message, lastBlockIndex), subkeys.subkey1);
} else {
lastBlock = xor(getPaddedMessageBlock(message, lastBlockIndex), subkeys.subkey2);
}
let x = zero;
let y;
for (let index = 0; index < lastBlockIndex; index++) {
y = xor(x, getMessageBlock(message, index));
x = aes(key, y);
}
y = xor(lastBlock, x);
return aes(key, y);
}
export class AesCmacProvider extends core.AesCmacProvider {
public async onGenerateKey(algorithm: AesKeyGenParams, extractable: boolean, keyUsages: KeyUsage[]): Promise<CryptoKey> {

View File

@ -1,11 +1,9 @@
import { JsonParser, JsonSerializer } from "@peculiar/json-schema";
import crypto, { CipherGCM, DecipherGCM } from "crypto";
import { JsonParser, JsonSerializer } from "@peculiar/json-schema";
import * as core from "webcrypto-core";
import { CryptoKey } from "../../keys";
import { AesCryptoKey } from "./key";
const WRONG_KEY_TYPE = `Key must be instance of ${AesCryptoKey.name}`;
export class AesCrypto {
public static AES_KW_IV = Buffer.from("A6A6A6A6A6A6A6A6", "hex");

View File

@ -1,5 +1,5 @@
import { JsonParser, JsonSerializer } from "@peculiar/json-schema";
import crypto from "crypto";
import { JsonParser, JsonSerializer } from "@peculiar/json-schema";
import * as core from "webcrypto-core";
import { DesParams } from "webcrypto-core";
import { CryptoKey } from "../../keys";

View File

@ -1,6 +1,6 @@
import crypto from "crypto";
import { AsnParser, AsnSerializer } from "@peculiar/asn1-schema";
import { JsonParser, JsonSerializer } from "@peculiar/json-schema";
import crypto from "crypto";
import * as core from "webcrypto-core";
import * as asn from "../../asn";
import { ObjectIdentifier } from "../../asn";
@ -116,9 +116,10 @@ export class EcCrypto {
case "pkcs8":
case "spki":
return new Uint8Array(key.data).buffer;
case "raw":
case "raw": {
const publicKeyInfo = AsnParser.parse(key.data, asn.PublicKeyInfo);
return publicKeyInfo.publicKey;
}
default:
throw new core.OperationError("format: Must be 'jwk', 'raw', pkcs8' or 'spki'");
}
@ -126,7 +127,7 @@ export class EcCrypto {
public static async importKey(format: KeyFormat, keyData: JsonWebKey | ArrayBuffer, algorithm: EcKeyImportParams, extractable: boolean, keyUsages: KeyUsage[]): Promise<CryptoKey> {
switch (format.toLowerCase()) {
case "jwk":
case "jwk": {
const jwk = keyData as JsonWebKey;
if (jwk.d) {
const asnKey = JsonParser.fromJSON(keyData, { targetSchema: asn.EcPrivateKey });
@ -135,6 +136,7 @@ export class EcCrypto {
const asnKey = JsonParser.fromJSON(keyData, { targetSchema: asn.EcPublicKey });
return this.importPublicKey(asnKey, algorithm, extractable, keyUsages);
}
}
case "raw": {
const asnKey = new asn.EcPublicKey(keyData as ArrayBuffer);
return this.importPublicKey(asnKey, algorithm, extractable, keyUsages);

View File

@ -29,14 +29,14 @@ export class EcPrivateKey extends AsymmetricKey implements IJsonConvertible {
}
public fromJSON(json: JsonWebKey) {
if (!json.alg) {
throw new core.OperationError(`Cannot get named curve from JWK. Property 'alg' is required`);
if (!json.crv) {
throw new core.OperationError(`Cannot get named curve from JWK. Property 'crv' is required`);
}
const keyInfo = new asn.PrivateKeyInfo();
keyInfo.privateKeyAlgorithm.algorithm = "1.2.840.10045.2.1";
keyInfo.privateKeyAlgorithm.parameters = AsnSerializer.serialize(
new ObjectIdentifier(getOidByNamedCurve(json.crv!)),
new ObjectIdentifier(getOidByNamedCurve(json.crv)),
);
const key = JsonParser.fromJSON(json, { targetSchema: asn.EcPrivateKey });
keyInfo.privateKey = AsnSerializer.serialize(key);

View File

@ -1,5 +1,6 @@
import { AsnParser, AsnSerializer } from "@peculiar/asn1-schema";
import { IJsonConvertible, JsonParser, JsonSerializer } from "@peculiar/json-schema";
import * as core from "webcrypto-core";
import * as asn from "../../asn";
import { ObjectIdentifier } from "../../asn";
import { AsymmetricKey } from "../../keys/asymmetric";
@ -29,12 +30,16 @@ export class EcPublicKey extends AsymmetricKey implements IJsonConvertible {
}
public fromJSON(json: JsonWebKey) {
if (!json.crv) {
throw new core.OperationError(`Cannot get named curve from JWK. Property 'crv' is required`);
}
const key = JsonParser.fromJSON(json, { targetSchema: asn.EcPublicKey });
const keyInfo = new asn.PublicKeyInfo();
keyInfo.publicKeyAlgorithm.algorithm = "1.2.840.10045.2.1";
keyInfo.publicKeyAlgorithm.parameters = AsnSerializer.serialize(
new ObjectIdentifier(getOidByNamedCurve(json.crv!)),
new ObjectIdentifier(getOidByNamedCurve(json.crv)),
);
keyInfo.publicKey = AsnSerializer.toASN(key).valueHex;

View File

@ -1,5 +1,5 @@
import { JsonParser, JsonSerializer } from "@peculiar/json-schema";
import crypto from "crypto";
import { JsonParser, JsonSerializer } from "@peculiar/json-schema";
import * as core from "webcrypto-core";
import { HmacCryptoKey } from "./key";

View File

@ -1,5 +1,4 @@
import { JsonProp } from "@peculiar/json-schema";
import * as core from "webcrypto-core";
import { JsonBase64UrlConverter } from "../../converters";
import { CryptoKey } from "../../keys";

View File

@ -1,4 +1,3 @@
import * as core from "webcrypto-core";
import { CryptoKey } from "../../keys";
export class PbkdfCryptoKey extends CryptoKey {

View File

@ -1,6 +1,6 @@
import crypto from "crypto";
import { AsnParser, AsnSerializer } from "@peculiar/asn1-schema";
import { JsonParser, JsonSerializer } from "@peculiar/json-schema";
import crypto from "crypto";
import * as core from "webcrypto-core";
import * as asn from "../../asn";
import { CryptoKey } from "../../keys";
@ -74,7 +74,7 @@ export class RsaCrypto {
public static async importKey(format: KeyFormat, keyData: JsonWebKey | ArrayBuffer, algorithm: RsaHashedImportParams, extractable: boolean, keyUsages: KeyUsage[]): Promise<CryptoKey> {
switch (format.toLowerCase()) {
case "jwk":
case "jwk": {
const jwk = keyData as JsonWebKey;
if (jwk.d) {
const asnKey = JsonParser.fromJSON(keyData, { targetSchema: asn.RsaPrivateKey });
@ -83,6 +83,7 @@ export class RsaCrypto {
const asnKey = JsonParser.fromJSON(keyData, { targetSchema: asn.RsaPublicKey });
return this.importPublicKey(asnKey, algorithm, extractable, keyUsages);
}
}
case "spki": {
const keyInfo = AsnParser.parse(new Uint8Array(keyData as ArrayBuffer), asn.PublicKeyInfo);
const asnKey = AsnParser.parse(keyInfo.publicKey, asn.RsaPublicKey);

View File

@ -1,10 +1,12 @@
/* eslint-disable @typescript-eslint/no-non-null-assertion */
import * as core from "webcrypto-core";
export function getJwkAlgorithm(algorithm: RsaHashedKeyAlgorithm) {
switch (algorithm.name.toUpperCase()) {
case "RSA-OAEP":
case "RSA-OAEP": {
const mdSize = /(\d+)$/.exec(algorithm.hash.name)![1];
return `RSA-OAEP${mdSize !== "1" ? `-${mdSize}` : ""}`;
}
case "RSASSA-PKCS1-V1_5":
return `RS${/(\d+)$/.exec(algorithm.hash.name)![1]}`;
case "RSA-PSS":

View File

@ -159,7 +159,7 @@ export class RsaOaepProvider extends core.RsaOaepProvider {
* @param seed
* @param length
*/
protected mgf1(algorithm: Algorithm, seed: Uint8Array, length: number = 0) {
protected mgf1(algorithm: Algorithm, seed: Uint8Array, length = 0) {
const hashSize = ShaCrypto.size(algorithm) >> 3;
const mask = new Uint8Array(length);
const counter = new Uint8Array(4);

View File

@ -1,6 +1,6 @@
import assert from "assert";
import { AsnParser, AsnSerializer } from "@peculiar/asn1-schema";
import { JsonParser, JsonSerializer } from "@peculiar/json-schema";
import assert from "assert";
import * as asn from "../src/asn";
context("ASN", () => {

View File

@ -1,4 +1,3 @@
import assert from "assert";
import * as core from "webcrypto-core";
import { Crypto } from "../src";
import { DesCbcParams } from "../src/mechs";

View File

@ -150,9 +150,10 @@ export function testCrypto(crypto: Crypto, params: ITestParams[]) {
params.forEach((param) => {
context(param.name, () => {
//#region Generate key
if (param.actions.generateKey) {
const generateKey = param.actions.generateKey;
if (generateKey) {
context("Generate Key", () => {
param.actions.generateKey!.forEach((action, index) => {
generateKey.forEach((action, index) => {
wrapTest(async () => {
const algorithm = Object.assign({}, action.algorithm);
algorithm.name = algorithm.name.toLowerCase();
@ -184,9 +185,10 @@ export function testCrypto(crypto: Crypto, params: ITestParams[]) {
//#endregion
//#region encrypt
if (param.actions.encrypt) {
const encrypt = param.actions.encrypt;
if (encrypt) {
context("Encrypt/Decrypt", () => {
param.actions.encrypt!.forEach((action, index) => {
encrypt.forEach((action, index) => {
wrapTest(async () => {
// import keys
const keys = await getKeys(crypto, action.key);
@ -212,9 +214,10 @@ export function testCrypto(crypto: Crypto, params: ITestParams[]) {
//#endregion
//#region Import/Export
if (param.actions.import) {
const importFn = param.actions.import;
if (importFn) {
context("Import/Export", () => {
param.actions.import!.forEach((action, index) => {
importFn.forEach((action, index) => {
wrapTest(async () => {
const importedKey = await crypto.subtle.importKey(
action.format,
@ -223,7 +226,7 @@ export function testCrypto(crypto: Crypto, params: ITestParams[]) {
action.extractable,
action.keyUsages);
// Can't continue if key is not exctractable.
// Can't continue if key is not extractable.
if (!action.extractable) {
return;
}
@ -244,9 +247,10 @@ export function testCrypto(crypto: Crypto, params: ITestParams[]) {
//#endregion
//#region Sign/Verify
if (param.actions.sign) {
const sign = param.actions.sign;
if (sign) {
context("Sign/Verify", () => {
param.actions.sign!.forEach((action, index) => {
sign.forEach((action, index) => {
wrapTest(async () => {
// import keys
const keys = await getKeys(crypto, action.key);
@ -275,9 +279,10 @@ export function testCrypto(crypto: Crypto, params: ITestParams[]) {
//#endregion
//#region Derive bits
if (param.actions.deriveBits) {
const deriveBits = param.actions.deriveBits;
if (deriveBits) {
context("Derive bits", () => {
param.actions.deriveBits!.forEach((action, index) => {
deriveBits.forEach((action, index) => {
wrapTest(async () => {
// import keys
const keys = await getKeys(crypto, action.key);
@ -295,9 +300,10 @@ export function testCrypto(crypto: Crypto, params: ITestParams[]) {
//#endregion
//#region Derive key
if (param.actions.deriveKey) {
const deriveKey = param.actions.deriveKey;
if (deriveKey) {
context("Derive key", () => {
param.actions.deriveKey!.forEach((action, index) => {
deriveKey.forEach((action, index) => {
wrapTest(async () => {
// import keys
const keys = await getKeys(crypto, action.key);
@ -320,9 +326,10 @@ export function testCrypto(crypto: Crypto, params: ITestParams[]) {
//#endregion
//#region Digest
if (param.actions.digest) {
const digest = param.actions.digest;
if (digest) {
context("Digest", () => {
param.actions.digest!.forEach((action, index) => {
digest.forEach((action, index) => {
wrapTest(async () => {
const hash = await crypto.subtle.digest(action.algorithm, action.data);
assert.equal(Convert.ToHex(hash), Convert.ToHex(action.hash));
@ -333,9 +340,10 @@ export function testCrypto(crypto: Crypto, params: ITestParams[]) {
//#endregion
//#region Wrap/Unwrap key
if (param.actions.wrapKey) {
const wrapKey = param.actions.wrapKey;
if (wrapKey) {
context("Wrap/Unwrap key", () => {
param.actions.wrapKey!.forEach((action, index) => {
wrapKey.forEach((action, index) => {
wrapTest(async () => {
const wKey = (await getKeys(crypto, action.wKey)).privateKey;
const key = await getKeys(crypto, action.key);

View File

@ -1,4 +1,3 @@
import { Convert } from "pvtsutils";
import { Crypto } from "../src";
import { testCrypto } from "./helper";

View File

@ -1,6 +1,6 @@
import { Convert } from "pvtsutils";
import { Crypto } from "../src";
import { ITestGenerateKeyAction, testCrypto } from "./helper";
import { testCrypto } from "./helper";
context("SHA", () => {

View File

@ -1,15 +0,0 @@
{
"defaultSeverity": "error",
"extends": [
"tslint:recommended"
],
"jsRules": {},
"rules": {
"max-line-length": false,
"no-bitwise": false,
"object-literal-sort-keys": false,
"no-namespace": false,
"max-classes-per-file": false
},
"rulesDirectory": []
}