Skip to content

Commit

Permalink
add base64url interface
Browse files Browse the repository at this point in the history
  • Loading branch information
jihyunlab-phil committed Dec 31, 2023
1 parent f29e306 commit 57647cb
Show file tree
Hide file tree
Showing 11 changed files with 215 additions and 34 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ You can use predefined functions to select the type of hash to generate.
Hash.create(HASH.SHA256).update('string').hex();
Hash.create(HASH.SHA256).update('string').binary();
Hash.create(HASH.SHA256).update('string').base64();
Hash.create(HASH.SHA256).update('string').base64url();
Hash.create(HASH.SHA256).update('string').buffer();
Hash.create(HASH.SHA256).update('string').uint8Array();
```
Expand Down Expand Up @@ -103,6 +104,9 @@ Cipher.create(CIPHER.AES_256_CBC, key).decrypt.binary(encrypted, iv);
Cipher.create(CIPHER.AES_256_CBC, key).encrypt.base64('string', iv);
Cipher.create(CIPHER.AES_256_CBC, key).decrypt.base64(encrypted, iv);

Cipher.create(CIPHER.AES_256_CBC, key).encrypt.base64url('string', iv);
Cipher.create(CIPHER.AES_256_CBC, key).decrypt.base64url(encrypted, iv);

Cipher.create(CIPHER.AES_256_CBC, key).encrypt.buffer(Buffer.from('string'), iv);
Cipher.create(CIPHER.AES_256_CBC, key).decrypt.buffer(encrypted, iv);

Expand Down
56 changes: 28 additions & 28 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 6 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@jihyunlab/crypto",
"version": "1.0.8",
"version": "1.0.9",
"description": "JihyunLab Crypto.",
"license": "MIT",
"author": "JihyunLab <info@jihyunlab.com> (https://jihyunlab.com)",
Expand Down Expand Up @@ -33,12 +33,12 @@
"node": ">=16"
},
"devDependencies": {
"@jihyunlab/eslint-config": "^1.1.1",
"@jihyunlab/prettier-config": "^1.1.1",
"@types/jest": "^29.5.8",
"@types/node": "^20.9.0",
"@jihyunlab/eslint-config": "^1.1.2",
"@jihyunlab/prettier-config": "^1.1.2",
"@types/jest": "^29.5.11",
"@types/node": "^20.10.6",
"jest": "^29.7.0",
"ts-jest": "^29.1.1",
"typescript": "^5.2.2"
"typescript": "^5.3.3"
}
}
13 changes: 13 additions & 0 deletions src/cryptos/aead/crypto.aead.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,15 @@ export class Aead {
return { text: string.text, tag: string.tag };
},

base64url(text: string, nonce: string | Buffer, inputEncoding?: crypto.Encoding) {
if (!inputEncoding) {
inputEncoding = 'utf8';
}

const string = this.string(text, nonce, inputEncoding, 'base64url');
return { text: string.text, tag: string.tag };
},

uint8Array(text: Buffer, nonce: string | Buffer) {
const buffer = this.buffer(text, nonce);
return { text: new Uint8Array(buffer.text), tag: buffer.tag };
Expand Down Expand Up @@ -148,6 +157,10 @@ export class Aead {
return this.string(text, tag, nonce, 'base64', outputEncoding);
},

base64url(text: string, tag: Buffer, nonce: string | Buffer, outputEncoding?: crypto.Encoding) {
return this.string(text, tag, nonce, 'base64url', outputEncoding);
},

uint8Array(text: Uint8Array, tag: Buffer, nonce: string | Buffer) {
const buffer = this.buffer(Buffer.from(text), tag, nonce);
return buffer;
Expand Down
12 changes: 12 additions & 0 deletions src/cryptos/cipher/crypto.cipher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,14 @@ export class Cipher {
return this.string(text, iv, inputEncoding, 'base64');
},

base64url(text: string, iv: string | Buffer | null, inputEncoding?: crypto.Encoding) {
if (!inputEncoding) {
inputEncoding = 'utf8';
}

return this.string(text, iv, inputEncoding, 'base64url');
},

uint8Array(text: Buffer, iv: string | Buffer | null) {
const buffer = this.buffer(text, iv);
return new Uint8Array(buffer);
Expand Down Expand Up @@ -84,6 +92,10 @@ export class Cipher {
return this.string(text, iv, 'base64', outputEncoding);
},

base64url(text: string, iv: string | Buffer | null, outputEncoding?: crypto.Encoding) {
return this.string(text, iv, 'base64url', outputEncoding);
},

uint8Array(text: Uint8Array, iv: string | Buffer | null) {
const buffer = this.buffer(Buffer.from(text), iv);
return buffer;
Expand Down
4 changes: 4 additions & 0 deletions src/cryptos/hash/crypto.hash.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ export class Hash {
return this.digest('base64').toString();
}

base64url() {
return this.digest('base64url').toString();
}

digest(encoding?: crypto.BinaryToTextEncoding) {
let result: string | Buffer;

Expand Down
4 changes: 4 additions & 0 deletions src/cryptos/hmac/crypto.hmac.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ export class Hmac {
return this.digest('base64').toString();
}

base64url() {
return this.digest('base64url').toString();
}

digest(encoding?: crypto.BinaryToTextEncoding) {
let result: string | Buffer;

Expand Down
44 changes: 44 additions & 0 deletions test/cryptos/aead.crypto.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,50 @@ describe('Aead', () => {
}
});

test('base64url()', () => {
const values = Object.values(AEAD);

for (let i = 0; i < values.length; i++) {
const name = values[i];

let key: string | Buffer = Helper.key.generate(name, passwordString, saltString);
let aead = Aead.create(name, key);
let nonce: string | Buffer;

nonce = Helper.nonce.generate(name);

let encrypted = aead.encrypt.base64url(textString, nonce);
let decrypted = aead.decrypt.base64url(encrypted.text, encrypted.tag, nonce);
expect(decrypted).toBe(textString);

key = Helper.key.normalize(name, key);
aead = Aead.create(name, key);

decrypted = aead.decrypt.base64url(encrypted.text, encrypted.tag, nonce);
expect(decrypted).toBe(textString);

key = Helper.key.generate(name, passwordBuffer, saltBuffer, PBKDF.PBKDF2, 2048, HASH.SHA256);
aead = Aead.create(name, key, authTagLength);
nonce = Helper.nonce.normalize(name, nonceString);

encrypted = aead.encrypt.base64url(textString, nonce);
decrypted = aead.decrypt.base64url(encrypted.text, encrypted.tag, nonce);
expect(decrypted).toBe(textString);

key = Helper.key.normalize(name, keyString);
aead = Aead.create(name, key, authTagLength, aad);
nonce = Helper.nonce.normalize(name, nonceBuffer);

encrypted = aead.encrypt.base64url(textString, nonce);

key = Helper.key.normalize(name, keyBuffer);
aead = Aead.create(name, key, authTagLength, aad);

decrypted = aead.decrypt.base64url(encrypted.text, encrypted.tag, nonce);
expect(decrypted).toBe(textString);
}
});

test('string()', () => {
const values = Object.values(AEAD);

Expand Down
44 changes: 44 additions & 0 deletions test/cryptos/cipher.crypto.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,50 @@ describe('Cipher', () => {
}
});

test('base64url()', () => {
const values = Object.values(CIPHER);

for (let i = 0; i < values.length; i++) {
const name = values[i];

let key: string | Buffer = Helper.key.generate(name, passwordString, saltString);
let crypto = Cipher.create(name, key);
let iv: string | Buffer | null;

iv = Helper.iv.generate(name);

let encrypted = crypto.encrypt.base64url(textString, iv);
let decrypted = crypto.decrypt.base64url(encrypted, iv);
expect(decrypted).toBe(textString);

key = Helper.key.normalize(name, key);
crypto = Cipher.create(name, key);

decrypted = crypto.decrypt.base64url(encrypted, iv);
expect(decrypted).toBe(textString);

key = Helper.key.generate(name, passwordBuffer, saltBuffer, PBKDF.PBKDF2, 2048, HASH.SHA256);
crypto = Cipher.create(name, key);
iv = Helper.iv.normalize(name, ivString);

encrypted = crypto.encrypt.base64url(textString, iv);
decrypted = crypto.decrypt.base64url(encrypted, iv);
expect(decrypted).toBe(textString);

key = Helper.key.normalize(name, keyString);
crypto = Cipher.create(name, key);
iv = Helper.iv.normalize(name, ivBuffer);

encrypted = crypto.encrypt.base64url(textString, iv);

key = Helper.key.normalize(name, keyBuffer);
crypto = Cipher.create(name, key);

decrypted = crypto.decrypt.base64url(encrypted, iv);
expect(decrypted).toBe(textString);
}
});

test('string()', () => {
const values = Object.values(CIPHER);

Expand Down
24 changes: 24 additions & 0 deletions test/cryptos/hash.crypto.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,29 @@ describe('Hash', () => {
}
});

test('base64url()', () => {
const values = Object.values(HASH);

for (let i = 0; i < values.length; i++) {
const name = values[i];
const hex = map.get(name);

if (!hex) {
continue;
}

let hash = Hash.create(name).update(textBuffer);
expect(hash.base64url()).toBe(Buffer.from(hex, 'hex').toString('base64url'));

hash = Hash.create(name).update(textString);
expect(hash.base64url()).toBe(Buffer.from(hex, 'hex').toString('base64url'));

hash = Hash.create(name);
expect(hash.update(textBuffer).base64url()).toBe(Buffer.from(hex, 'hex').toString('base64url'));
expect(hash.update(textBuffer).base64url()).toBe(Buffer.from(hex, 'hex').toString('base64url'));
}
});

test('buffer()', () => {
const values = Object.values(HASH);

Expand Down Expand Up @@ -174,6 +197,7 @@ describe('Hash', () => {
expect(Hash.create('sha256').update(textString).binary()).toEqual(Buffer.from(hex, 'hex').toString('binary'));
expect(Hash.create('sha256').update(textString).hex()).toEqual(Buffer.from(hex, 'hex').toString('hex'));
expect(Hash.create('sha256').update(textString).base64()).toEqual(Buffer.from(hex, 'hex').toString('base64'));
expect(Hash.create('sha256').update(textString).base64url()).toEqual(Buffer.from(hex, 'hex').toString('base64url'));
expect(Hash.create('sha256').update(textString).buffer()).toEqual(Buffer.from(hex, 'hex'));
expect(Hash.create('sha256').update(textString).uint8Array()).toStrictEqual(
new Uint8Array(Buffer.from(hex, 'hex'))
Expand Down
Loading

0 comments on commit 57647cb

Please sign in to comment.