Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove charSize. Always use utf8. #63

Draft
wants to merge 6 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions src/aes/keys.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { webcrypto } from 'one-webcrypto'
import utils from '../utils.js'
import * as uint8arrays from "uint8arrays"

import { DEFAULT_SYMM_ALG, DEFAULT_SYMM_LEN } from '../constants.js'
import { SymmKey, SymmKeyOpts } from '../types.js'

Expand All @@ -15,7 +16,7 @@ export async function makeKey(opts?: Partial<SymmKeyOpts>): Promise<SymmKey> {
}

export async function importKey(base64key: string, opts?: Partial<SymmKeyOpts>): Promise<SymmKey> {
const buf = utils.base64ToArrBuf(base64key)
const buf = uint8arrays.fromString(base64key, "base64pad")
return webcrypto.subtle.importKey(
'raw',
buf,
Expand Down
20 changes: 11 additions & 9 deletions src/aes/operations.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { webcrypto } from 'one-webcrypto'
import * as uint8arrays from "uint8arrays"

import keys from './keys.js'
import utils from '../utils.js'
import { DEFAULT_SYMM_ALG, DEFAULT_CTR_LEN } from '../constants.js'
Expand All @@ -9,7 +11,7 @@ export async function encryptBytes(
key: SymmKey | string,
opts?: Partial<SymmKeyOpts>
): Promise<CipherText> {
const data = utils.normalizeUtf16ToBuf(msg)
const data = utils.normalizeUnicodeToBuf(msg)
const importedKey = typeof key === 'string' ? await keys.importKey(key, opts) : key
const alg = opts?.alg || DEFAULT_SYMM_ALG
const iv = opts?.iv || utils.randomBuf(16)
Expand All @@ -18,20 +20,20 @@ export async function encryptBytes(
name: alg,
// AES-CTR uses a counter, AES-GCM/AES-CBC use an initialization vector
iv: alg === SymmAlg.AES_CTR ? undefined : iv,
counter: alg === SymmAlg.AES_CTR ? new Uint8Array(iv) : undefined,
counter: alg === SymmAlg.AES_CTR ? iv : undefined,
length: alg === SymmAlg.AES_CTR ? DEFAULT_CTR_LEN : undefined,
},
importedKey,
data
)
return utils.joinBufs(iv, cipherBuf)
return uint8arrays.concat([iv, new Uint8Array(cipherBuf)])
}

export async function decryptBytes(
msg: Msg,
key: SymmKey | string,
opts?: Partial<SymmKeyOpts>
): Promise<ArrayBuffer> {
): Promise<Uint8Array> {
const cipherText = utils.normalizeBase64ToBuf(msg)
const importedKey = typeof key === 'string' ? await keys.importKey(key, opts) : key
const alg = opts?.alg || DEFAULT_SYMM_ALG
Expand All @@ -41,13 +43,13 @@ export async function decryptBytes(
{ name: alg,
// AES-CTR uses a counter, AES-GCM/AES-CBC use an initialization vector
iv: alg === SymmAlg.AES_CTR ? undefined : iv,
counter: alg === SymmAlg.AES_CTR ? new Uint8Array(iv) : undefined,
counter: alg === SymmAlg.AES_CTR ? iv : undefined,
length: alg === SymmAlg.AES_CTR ? DEFAULT_CTR_LEN : undefined,
},
importedKey,
cipherBytes
)
return msgBuff
return new Uint8Array(msgBuff)
}

export async function encrypt(
Expand All @@ -56,7 +58,7 @@ export async function encrypt(
opts?: Partial<SymmKeyOpts>
): Promise<string> {
const cipherText = await encryptBytes(msg, key, opts)
return utils.arrBufToBase64(cipherText)
return uint8arrays.toString(cipherText, "base64pad")
}

export async function decrypt(
Expand All @@ -65,13 +67,13 @@ export async function decrypt(
opts?: Partial<SymmKeyOpts>
): Promise<string> {
const msgBytes = await decryptBytes(msg, key, opts)
return utils.arrBufToStr(msgBytes, 16)
return uint8arrays.toString(msgBytes, "utf8")
}


export async function exportKey(key: SymmKey): Promise<string> {
const raw = await webcrypto.subtle.exportKey('raw', key)
return utils.arrBufToBase64(raw)
return uint8arrays.toString(new Uint8Array(raw), "base64pad")
}

export default {
Expand Down
4 changes: 1 addition & 3 deletions src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import {
DEFAULT_SYMM_ALG,
DEFAULT_SYMM_LEN,
DEFAULT_HASH_ALG,
DEFAULT_CHAR_SIZE,
DEFAULT_STORE_NAME,
DEFAULT_EXCHANGE_KEY_NAME,
DEFAULT_WRITE_KEY_NAME
Expand All @@ -21,15 +20,14 @@ export const defaultConfig = {
symmAlg: DEFAULT_SYMM_ALG,
symmLen: DEFAULT_SYMM_LEN,
hashAlg: DEFAULT_HASH_ALG,
charSize: DEFAULT_CHAR_SIZE,
storeName: DEFAULT_STORE_NAME,
exchangeKeyName: DEFAULT_EXCHANGE_KEY_NAME,
writeKeyName: DEFAULT_WRITE_KEY_NAME
} as Config

export function normalize(
maybeCfg?: Partial<Config>,
eccEnabled: boolean = true
eccEnabled = true
): Config {
let cfg
if (!maybeCfg) {
Expand Down
4 changes: 1 addition & 3 deletions src/constants.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { EccCurve, RsaSize, SymmAlg, SymmKeyLength, HashAlg, CharSize } from './types.js'
import { EccCurve, RsaSize, SymmAlg, SymmKeyLength, HashAlg } from './types.js'

export const ECC_EXCHANGE_ALG = 'ECDH'
export const ECC_WRITE_ALG = 'ECDSA'
Expand All @@ -15,7 +15,6 @@ export const DEFAULT_SYMM_LEN = SymmKeyLength.B256
export const DEFAULT_CTR_LEN = 64

export const DEFAULT_HASH_ALG = HashAlg.SHA_256
export const DEFAULT_CHAR_SIZE = CharSize.B16

export const DEFAULT_STORE_NAME = 'keystore'
export const DEFAULT_EXCHANGE_KEY_NAME = 'exchange-key'
Expand All @@ -33,7 +32,6 @@ export default {
DEFAULT_SYMM_ALG,
DEFAULT_CTR_LEN,
DEFAULT_HASH_ALG,
DEFAULT_CHAR_SIZE,
DEFAULT_STORE_NAME,
DEFAULT_EXCHANGE_KEY_NAME,
DEFAULT_WRITE_KEY_NAME,
Expand Down
5 changes: 3 additions & 2 deletions src/ecc/keys.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { webcrypto } from 'one-webcrypto'
import utils from '../utils.js'
import * as uint8arrays from "uint8arrays"

import { ECC_EXCHANGE_ALG, ECC_WRITE_ALG } from '../constants.js'
import { EccCurve, KeyUse, PublicKey } from '../types.js'
import { checkValidKeyUse } from '../errors.js'
Expand All @@ -24,7 +25,7 @@ export async function importPublicKey(base64Key: string, curve: EccCurve, use: K
const alg = use === KeyUse.Exchange ? ECC_EXCHANGE_ALG : ECC_WRITE_ALG
const uses: KeyUsage[] =
use === KeyUse.Exchange ? [] : ['verify']
const buf = utils.base64ToArrBuf(base64Key)
const buf = uint8arrays.fromString(base64Key, "base64pad")
return webcrypto.subtle.importKey(
'raw',
buf,
Expand Down
18 changes: 8 additions & 10 deletions src/ecc/keystore.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import * as uint8arrays from "uint8arrays"

import IDB from '../idb.js'
import keys from './keys.js'
import operations from './operations.js'
import config from '../config.js'
import utils from '../utils.js'
import KeyStoreBase from '../keystore/base.js'
import { KeyStore, Config, KeyUse, CryptoSystem, PrivateKey } from '../types.js'

Expand Down Expand Up @@ -31,12 +32,11 @@ export class ECCKeyStore extends KeyStoreBase implements KeyStore {
const mergedCfg = config.merge(this.cfg, cfg)
const writeKey = await this.writeKey()

return utils.arrBufToBase64(await operations.sign(
return uint8arrays.toString(await operations.sign(
msg,
writeKey.privateKey as PrivateKey,
mergedCfg.charSize,
mergedCfg.hashAlg
))
), "base64pad")
}

async verify(
Expand All @@ -51,7 +51,6 @@ export class ECCKeyStore extends KeyStoreBase implements KeyStore {
msg,
sig,
publicKey,
mergedCfg.charSize,
mergedCfg.curve,
mergedCfg.hashAlg
)
Expand All @@ -65,13 +64,12 @@ export class ECCKeyStore extends KeyStoreBase implements KeyStore {
const mergedCfg = config.merge(this.cfg, cfg)
const exchangeKey = await this.exchangeKey()

return utils.arrBufToBase64(await operations.encrypt(
return uint8arrays.toString(await operations.encrypt(
msg,
exchangeKey.privateKey as PrivateKey,
publicKey,
mergedCfg.charSize,
mergedCfg.curve
))
), "base64pad")
}

async decrypt(
Expand All @@ -82,14 +80,14 @@ export class ECCKeyStore extends KeyStoreBase implements KeyStore {
const mergedCfg = config.merge(this.cfg, cfg)
const exchangeKey = await this.exchangeKey()

return utils.arrBufToStr(
return uint8arrays.toString(
await operations.decrypt(
cipherText,
exchangeKey.privateKey as PrivateKey,
publicKey,
mergedCfg.curve
),
mergedCfg.charSize
"utf8"
)
}

Expand Down
35 changes: 17 additions & 18 deletions src/ecc/operations.ts
Original file line number Diff line number Diff line change
@@ -1,29 +1,29 @@
import * as uint8arrays from "uint8arrays"
import { webcrypto } from 'one-webcrypto'

import aes from '../aes/index.js'
import keys from './keys.js'
import utils, { normalizeBase64ToBuf, normalizeUnicodeToBuf } from '../utils.js'
import { DEFAULT_CHAR_SIZE, DEFAULT_ECC_CURVE, DEFAULT_HASH_ALG, ECC_EXCHANGE_ALG, ECC_WRITE_ALG, DEFAULT_SYMM_ALG, DEFAULT_SYMM_LEN } from '../constants.js'
import { CharSize, EccCurve, Msg, PrivateKey, PublicKey, HashAlg, KeyUse, SymmKey, SymmKeyOpts } from '../types.js'
import { webcrypto } from 'one-webcrypto'
import { normalizeAssumingBase64, normalizeAssumingUtf8 } from '../utils.js'
import { DEFAULT_ECC_CURVE, DEFAULT_HASH_ALG, ECC_EXCHANGE_ALG, ECC_WRITE_ALG, DEFAULT_SYMM_ALG, DEFAULT_SYMM_LEN } from '../constants.js'
import { EccCurve, Msg, PrivateKey, PublicKey, HashAlg, KeyUse, SymmKey, SymmKeyOpts } from '../types.js'


export async function sign(
msg: Msg,
privateKey: PrivateKey,
charSize: CharSize = DEFAULT_CHAR_SIZE,
hashAlg: HashAlg = DEFAULT_HASH_ALG,
): Promise<ArrayBuffer> {
return webcrypto.subtle.sign(
): Promise<Uint8Array> {
return new Uint8Array(await webcrypto.subtle.sign(
{ name: ECC_WRITE_ALG, hash: { name: hashAlg }},
privateKey,
normalizeUnicodeToBuf(msg, charSize)
)
normalizeAssumingUtf8(msg)
))
}

export async function verify(
msg: Msg,
sig: Msg,
publicKey: string | PublicKey,
charSize: CharSize = DEFAULT_CHAR_SIZE,
curve: EccCurve = DEFAULT_ECC_CURVE,
hashAlg: HashAlg = DEFAULT_HASH_ALG
): Promise<boolean> {
Expand All @@ -32,25 +32,24 @@ export async function verify(
typeof publicKey === "string"
? await keys.importPublicKey(publicKey, curve, KeyUse.Write)
: publicKey,
normalizeBase64ToBuf(sig),
normalizeUnicodeToBuf(msg, charSize)
normalizeAssumingBase64(sig),
normalizeAssumingUtf8(msg)
)
}

export async function encrypt(
msg: Msg,
privateKey: PrivateKey,
publicKey: string | PublicKey,
charSize: CharSize = DEFAULT_CHAR_SIZE,
curve: EccCurve = DEFAULT_ECC_CURVE,
opts?: Partial<SymmKeyOpts>
): Promise<ArrayBuffer> {
): Promise<Uint8Array> {
const importedPublicKey = typeof publicKey === "string"
? await keys.importPublicKey(publicKey, curve, KeyUse.Exchange)
: publicKey

const cipherKey = await getSharedKey(privateKey, importedPublicKey, opts)
return aes.encryptBytes(normalizeUnicodeToBuf(msg, charSize), cipherKey, opts)
return aes.encryptBytes(normalizeAssumingUtf8(msg), cipherKey, opts)
}

export async function decrypt(
Expand All @@ -59,18 +58,18 @@ export async function decrypt(
publicKey: string | PublicKey,
curve: EccCurve = DEFAULT_ECC_CURVE,
opts?: Partial<SymmKeyOpts>
): Promise<ArrayBuffer> {
): Promise<Uint8Array> {
const importedPublicKey = typeof publicKey === "string"
? await keys.importPublicKey(publicKey, curve, KeyUse.Exchange)
: publicKey

const cipherKey = await getSharedKey(privateKey, importedPublicKey, opts)
return aes.decryptBytes(normalizeBase64ToBuf(msg), cipherKey, opts)
return aes.decryptBytes(normalizeAssumingBase64(msg), cipherKey, opts)
}

export async function getPublicKey(keypair: CryptoKeyPair): Promise<string> {
const raw = await webcrypto.subtle.exportKey('raw', keypair.publicKey as PublicKey)
return utils.arrBufToBase64(raw)
return uint8arrays.toString(new Uint8Array(raw), "base64pad")
}

export async function getSharedKey(privateKey: PrivateKey, publicKey: PublicKey, opts?: Partial<SymmKeyOpts>): Promise<SymmKey> {
Expand Down
11 changes: 6 additions & 5 deletions src/keystore/base.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import * as uint8arrays from "uint8arrays"

import aes from '../aes/index.js'
import idb from '../idb.js'
import utils from '../utils.js'
import config from '../config.js'
import { Config } from '../types.js'
import { checkIsKeyPair } from '../errors.js'
Expand Down Expand Up @@ -64,21 +65,21 @@ export default class KeyStoreBase {
const mergedCfg = config.merge(this.cfg, cfg)
const key = await this.getSymmKey(keyName, cfg)
const cipherText = await aes.encryptBytes(
utils.strToArrBuf(msg, mergedCfg.charSize),
uint8arrays.fromString(msg, "utf8"),
key,
config.symmKeyOpts(mergedCfg)
)
return utils.arrBufToBase64(cipherText)
return uint8arrays.toString(cipherText, "base64pad")
}

async decryptWithSymmKey(cipherText: string, keyName: string, cfg?: Partial<Config>): Promise<string> {
const mergedCfg = config.merge(this.cfg, cfg)
const key = await this.getSymmKey(keyName, cfg)
const msgBytes = await aes.decryptBytes(
utils.base64ToArrBuf(cipherText),
uint8arrays.fromString(cipherText, "base64pad"),
key,
config.symmKeyOpts(mergedCfg)
)
return utils.arrBufToStr(msgBytes, mergedCfg.charSize)
return uint8arrays.toString(new Uint8Array(msgBytes), "utf8")
}
}
6 changes: 3 additions & 3 deletions src/keystore/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,17 @@ import { Config, KeyStore } from '../types.js'

export async function init(maybeCfg?: Partial<Config>): Promise<KeyStore>{
const eccEnabled = await config.eccEnabled()
if(!eccEnabled && maybeCfg?.type === 'ecc'){
if (!eccEnabled && maybeCfg?.type === 'ecc') {
throw ECCNotEnabled
}

const cfg = config.normalize(maybeCfg, eccEnabled)

checkValidCryptoSystem(cfg.type)

if(cfg.type === 'ecc'){
if (cfg.type === 'ecc') {
return ECCKeyStore.init(cfg)
}else {
} else {
return RSAKeyStore.init(cfg)
}
}
Expand Down
4 changes: 3 additions & 1 deletion src/rsa/keys.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { webcrypto } from 'one-webcrypto'
import * as uint8arrays from "uint8arrays"

import { RSA_EXCHANGE_ALG, RSA_WRITE_ALG } from '../constants.js'
import { RsaSize, HashAlg, KeyUse, PublicKey } from '../types.js'
import utils from '../utils.js'
Expand Down Expand Up @@ -34,7 +36,7 @@ export async function importPublicKey(base64Key: string, hashAlg: HashAlg, use:
checkValidKeyUse(use)
const alg = use === KeyUse.Exchange ? RSA_EXCHANGE_ALG : RSA_WRITE_ALG
const uses: KeyUsage[] = use === KeyUse.Exchange ? ['encrypt'] : ['verify']
const buf = utils.base64ToArrBuf(stripKeyHeader(base64Key))
const buf = uint8arrays.fromString(stripKeyHeader(base64Key), "base64pad")
return webcrypto.subtle.importKey(
'spki',
buf,
Expand Down
Loading