22 Commits

Author SHA1 Message Date
72a31ab3e2 update deps 2024-03-19 13:52:14 +01:00
629e3af60d pipeline 2024-02-09 14:44:04 +01:00
bfc4ca3c48 pipeline 2024-02-09 14:41:19 +01:00
0798993f84 install browsers 2024-02-09 14:34:53 +01:00
bac19fa91d update deps 2024-02-09 14:32:04 +01:00
dependabot[bot]
6bbc5979ae Bump follow-redirects from 1.15.2 to 1.15.4 (#5)
Bumps [follow-redirects](https://github.com/follow-redirects/follow-redirects) from 1.15.2 to 1.15.4.
- [Release notes](https://github.com/follow-redirects/follow-redirects/releases)
- [Commits](https://github.com/follow-redirects/follow-redirects/compare/v1.15.2...v1.15.4)

---
updated-dependencies:
- dependency-name: follow-redirects
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-09 14:24:59 +01:00
dependabot[bot]
be04f9c546 Bump socket.io-parser from 4.2.2 to 4.2.4 (#4)
Bumps [socket.io-parser](https://github.com/socketio/socket.io-parser) from 4.2.2 to 4.2.4.
- [Release notes](https://github.com/socketio/socket.io-parser/releases)
- [Changelog](https://github.com/socketio/socket.io-parser/blob/main/CHANGELOG.md)
- [Commits](https://github.com/socketio/socket.io-parser/compare/4.2.2...4.2.4)

---
updated-dependencies:
- dependency-name: socket.io-parser
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-21 10:48:06 +01:00
f4503bbf2b changelog 2023-05-16 10:30:28 +02:00
69c444a204 2.0.2 2023-05-16 10:30:12 +02:00
ffc6e62f7c update deps 2023-05-16 10:28:44 +02:00
dcfd25c823 update deps 2023-04-27 22:30:22 +02:00
5e811edbc5 changelog 2023-04-25 00:07:31 +02:00
66b54dd27d 2.0.1 2023-04-25 00:06:41 +02:00
2d23b95605 update deps 2023-04-25 00:06:36 +02:00
1ab82a78fe readme 2023-01-14 18:49:31 +01:00
5babec20ce stable version 2023-01-14 18:42:49 +01:00
d1b07e0a81 add generate key 2023-01-13 20:42:36 +01:00
f2f8607c39 aes testing 2022-10-18 17:37:04 +02:00
8397b7fc26 add tests for binary 2022-10-18 17:27:14 +02:00
211d5f7629 add tests for hex 2022-10-18 16:59:33 +02:00
5ce25e41c2 version bump 2022-10-18 16:20:41 +02:00
0b70c729ce no git checks in ci 2022-10-18 16:20:09 +02:00
14 changed files with 1082 additions and 600 deletions

View File

@@ -1,9 +1,9 @@
name: "Publish to NPM" name: 'Publish to NPM'
on: on:
push: push:
tags: tags:
- "v*" - 'v*'
jobs: jobs:
build: build:
@@ -16,22 +16,22 @@ jobs:
- name: Install Node - name: Install Node
uses: actions/setup-node@v3 uses: actions/setup-node@v3
with: with:
node-version: 16 node-version-file: '.nvmrc'
registry-url: "https://registry.npmjs.org" registry-url: 'https://registry.npmjs.org'
- name: Setup PNPM - name: Setup PNPM
uses: pnpm/action-setup@v2 uses: pnpm/action-setup@v2
with:
version: 7
- name: Install dependencies - name: Install dependencies
run: pnpm install run: pnpm install
- name: Install Playwright - name: Install Playwright Dependencies
run: pnpm exec playwright install-deps run: pnpm exec playwright install-deps
- name: Install Playwright Browsers
run: pnpm exec playwright install
- name: Run tests - name: Run tests
run: pnpm run test run: pnpm run test
- name: Release - name: Release
run: pnpm publish run: pnpm publish --no-git-checks
env: env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

View File

@@ -1,4 +1,4 @@
name: "Run Tests" name: 'Run Tests'
on: on:
pull_request: pull_request:
@@ -17,16 +17,16 @@ jobs:
- name: Install Node - name: Install Node
uses: actions/setup-node@v3 uses: actions/setup-node@v3
with: with:
node-version: 16 node-version-file: .nvmrc
- name: Setup PNPM - name: Setup PNPM
uses: pnpm/action-setup@v2 uses: pnpm/action-setup@v2
with:
version: 7
- name: Install dependencies - name: Install dependencies
run: pnpm install run: pnpm install
- name: Install Playwright - name: Install Playwright Dependencies
run: pnpm exec playwright install-deps run: pnpm exec playwright install-deps
- name: Install Playwright Browsers
run: pnpm exec playwright install
- name: Run tests - name: Run tests
run: pnpm run test run: pnpm run test

1
.npmrc
View File

@@ -1 +0,0 @@
engine-strict=true

1
.nvmrc Normal file
View File

@@ -0,0 +1 @@
v20

View File

@@ -5,6 +5,30 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [2.0.4]
### Changed
- Updated dependencies.
## [2.0.3]
### Changed
- Updated dependencies.
## [2.0.2]
### Changed
- Updated dependencies.
## [2.0.1]
### Changed
- Updated dependencies.
## [2.0.0] ## [2.0.0]
### Added ### Added

View File

@@ -33,8 +33,10 @@ npm i occulto
```typescript ```typescript
import { RSA } from 'occulto' import { RSA } from 'occulto'
const pair = await RSA.generateKeyPair() const pair = await RSA.generateKeyPair(2 ** 11)
const encrypted = await RSA.encrypt('some text', pair.public) const bytes = Bytes.encode(message)
const encrypted = await RSA.encrypt(bytes, pair.public)
const decrypted = await RSA.decrypt(encrypted, pair.private) const decrypted = await RSA.decrypt(encrypted, pair.private)
``` ```
@@ -42,11 +44,29 @@ const decrypted = await RSA.decrypt(encrypted, pair.private)
[Available Modes](https://occulto.pages.dev/enums/Modes) [Available Modes](https://occulto.pages.dev/enums/Modes)
```javascript There is an _easy_ API, that will take care of everything for you.
import { Symmetric } from 'occulto'
const encrypted = await Symmetric.encryptEasy('some string', 'myPass') ```typescript
const decrypted = await Symmetric.decryptEasy(encrypted, 'myPass') import { AES } from 'occulto'
const password = 'foobar'
const message = 'this is a secret'
const encrypted = await AES.encryptEasy(message, password)
const decrypted = await AES.decryptEasy(encrypted, password)
```
The low level API is also exposed for advanced usages.
```typescript
import { AES } from 'occulto'
const message = 'this is a secret'
const key = await AES.generateKey()
const data = Bytes.encode(message)
const ciphertext = await AES.encrypt(data, key)
const plaintext = await AES.decrypt(ciphertext, key)
``` ```
### [Hash](https://occulto.pages.dev/classes/Hash) ### [Hash](https://occulto.pages.dev/classes/Hash)
@@ -54,9 +74,7 @@ const decrypted = await Symmetric.decryptEasy(encrypted, 'myPass')
[Available hashes](https://occulto.pages.dev/enums/Hashes) [Available hashes](https://occulto.pages.dev/enums/Hashes)
```typescript ```typescript
import { Hash } from 'occulto' import { Hash, Hashes } from 'occulto'
const hash = Hash.digest('something') const hashed = await Hash.hash('Some value', Hashes.SHA_512)
const h = Hash.digest('something', Hash.Hashes.MD5)
``` ```

View File

@@ -1,7 +1,6 @@
{ {
"name": "occulto", "name": "occulto",
"version": "2.0.0-rc.8", "version": "2.0.4",
"license": "MIT",
"description": "crypt utility", "description": "crypt utility",
"keywords": [ "keywords": [
"isomorphic", "isomorphic",
@@ -9,20 +8,24 @@
"aes", "aes",
"rsa" "rsa"
], ],
"engines": { "repository": {
"node": ">=16", "type": "git",
"npm": "please-use-pnpm", "url": "https://github.com/cupcakearmy/occulto"
"yarn": "please-use-pnpm", },
"pnpm": "7" "license": "MIT",
"author": {
"name": "Niccolo Borgioli",
"email": "opensource@nicco.io",
"url": "https://nicco.io"
}, },
"type": "module", "type": "module",
"types": "./dist/index.d.ts",
"exports": { "exports": {
".": { ".": {
"types": "./dist/index.d.ts", "types": "./dist/index.d.ts",
"import": "./dist/index.js" "import": "./dist/index.js"
} }
}, },
"types": "./dist/index.d.ts",
"files": [ "files": [
"dist" "dist"
], ],
@@ -41,23 +44,21 @@
}, },
"devDependencies": { "devDependencies": {
"@endyjasmi/karma-playwright-launcher": "^0.0.4", "@endyjasmi/karma-playwright-launcher": "^0.0.4",
"@types/node": "^16.11.66", "@types/node": "^20.11.30",
"chai": "^4.3.6", "chai": "^4.4.1",
"karma": "^6.4.1", "karma": "^6.4.3",
"karma-mocha": "^2.0.1", "karma-mocha": "^2.0.1",
"mocha": "^10.1.0", "mocha": "^10.3.0",
"npm-run-all": "^4.1.5", "npm-run-all": "^4.1.5",
"playwright": "^1.27.1", "playwright": "^1.42.1",
"typedoc": "^0.23.17", "typedoc": "^0.25.12",
"typescript": "^4.8.4" "typescript": "^5.4.2"
}, },
"repository": { "packageManager": "pnpm@8.15.5",
"type": "git", "engines": {
"url": "https://github.com/cupcakearmy/occulto" "node": ">=16",
}, "npm": "please-use-pnpm",
"author": { "pnpm": ">=8",
"name": "Niccolo Borgioli", "yarn": "please-use-pnpm"
"email": "opensource@nicco.io",
"url": "https://nicco.io"
} }
} }

1422
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@@ -29,7 +29,8 @@ export enum Modes {
export class AES { export class AES {
static Modes = Modes static Modes = Modes
private static delimiter = '--' // delimiter with a character that is not allowed in base64 or hex // delimiter with a character that is not allowed in base64 or hex
private static delimiter = '--'
private static delimiterEasy = '---' private static delimiterEasy = '---'
private static InvalidCiphertext = new Error('Invalid ciphertext') private static InvalidCiphertext = new Error('Invalid ciphertext')
@@ -141,4 +142,18 @@ export class AES {
const decrypted = await this.decrypt(data, keyDerived) const decrypted = await this.decrypt(data, keyDerived)
return Bytes.decode(decrypted) return Bytes.decode(decrypted)
} }
static async generateKey(): Promise<TypedArray> {
const c = await getCrypto()
const key = await c.subtle.generateKey(
{
name: 'AES-GCM',
length: 256,
},
true,
['encrypt', 'decrypt']
)
const buffer = await c.subtle.exportKey('raw', key)
return new Uint8Array(buffer)
}
} }

View File

@@ -3,4 +3,4 @@ export * from './crypto/encoding.js'
export * from './crypto/hash.js' export * from './crypto/hash.js'
export * from './crypto/random.js' export * from './crypto/random.js'
export * from './crypto/rsa.js' export * from './crypto/rsa.js'
export * from './utils/base.js' export { TypedArray } from './utils/base.js'

View File

@@ -2,14 +2,17 @@ import { AES, Bytes, Hashes, Hex } from '../dist/index.js'
import { Precomputed } from './values.js' import { Precomputed } from './values.js'
describe('AES', () => { describe('AES', () => {
it('Basic API', async () => { for (const message of Object.values(Precomputed.Crypto.Messages)) {
const message = Precomputed.Crypto.Messages.nietzscheIpsum describe(`Message: ${message.slice(0, 8)}...`, () => {
describe('Basic API', () => {
for (const keySize of [128, 256]) {
it('Key Size: ' + keySize, async () => {
const data = Bytes.encode(message) const data = Bytes.encode(message)
const [key] = await AES.derive('foo', { const [key] = await AES.derive('foo', {
name: 'PBKDF2', name: 'PBKDF2',
hash: Hashes.SHA_512, hash: Hashes.SHA_512,
iterations: 1000, iterations: 1000,
length: 256, length: keySize,
salt: Hex.decode(Precomputed.Crypto.Bytes[16]), salt: Hex.decode(Precomputed.Crypto.Bytes[16]),
}) })
const ciphertext = await AES.encrypt(data, key, AES.Modes.GCM) const ciphertext = await AES.encrypt(data, key, AES.Modes.GCM)
@@ -17,12 +20,24 @@ describe('AES', () => {
chai.expect(data).to.be.deep.equal(plaintext) chai.expect(data).to.be.deep.equal(plaintext)
chai.expect(message).to.be.equal(Bytes.decode(plaintext)) chai.expect(message).to.be.equal(Bytes.decode(plaintext))
}) })
}
})
it('Generated Key', async () => {
const key = await AES.generateKey()
const data = Bytes.encode(message)
const ciphertext = await AES.encrypt(data, key)
const plaintext = await AES.decrypt(ciphertext, key)
chai.expect(data).to.be.deep.equal(plaintext)
chai.expect(message).to.be.equal(Bytes.decode(plaintext))
})
it('Easy API', async () => { it('Easy API', async () => {
const message = Precomputed.Crypto.Messages.nietzscheIpsum
const password = 'foobar' const password = 'foobar'
const encrypted = await AES.encryptEasy(message, password) const encrypted = await AES.encryptEasy(message, password)
const decrypted = await AES.decryptEasy(encrypted, password) const decrypted = await AES.decryptEasy(encrypted, password)
chai.expect(message).to.be.equal(decrypted) chai.expect(message).to.be.equal(decrypted)
}) })
})
}
}) })

View File

@@ -1,7 +1,29 @@
import { Base64, Bytes } from '../dist/index.js' import { Base64, Bytes, Hex } from '../dist/index.js'
import { compareArrayLike } from './utils.js'
import { Precomputed } from './values.js' import { Precomputed } from './values.js'
describe('Encoding', () => { describe('Encoding', () => {
describe('Bytes', () => {
for (const [input, output] of Object.entries(Precomputed.Encoding.Bytes)) {
it(`Should encode ${input} to ${output}`, async () => {
compareArrayLike(Bytes.encode(input), output)
})
it(`Should decode ${output} to ${input}`, async () => {
compareArrayLike(await Bytes.decode(output), input)
})
}
})
describe('Hex', () => {
for (const [input, output] of Object.entries(Precomputed.Encoding.Hex)) {
const buffer = Bytes.encode(input)
it(`Should encode ${input} to ${output}`, async () => {
chai.expect(await Hex.encode(buffer)).to.equal(output)
})
it(`Should decode ${output} to ${input}`, async () => {
chai.expect(await Hex.decode(output)).to.deep.equal(buffer)
})
}
})
describe('Base64', () => { describe('Base64', () => {
for (const [input, output] of Object.entries(Precomputed.Encoding.Base64)) { for (const [input, output] of Object.entries(Precomputed.Encoding.Base64)) {
const buffer = Bytes.encode(input) const buffer = Bytes.encode(input)

View File

@@ -6,3 +6,10 @@ export class Promises {
} catch {} } catch {}
} }
} }
export function compareArrayLike(a, b) {
chai.expect(a.length).to.equal(b.length)
for (let i = 0; i < a.length; i++) {
chai.expect(a[i]).to.equal(b[i])
}
}

View File

@@ -5,6 +5,18 @@ export const Precomputed = {
test: 'dGVzdA==', test: 'dGVzdA==',
'hello world': 'aGVsbG8gd29ybGQ=', 'hello world': 'aGVsbG8gd29ybGQ=',
}, },
Hex: {
test: '74657374',
occulto: '6f6363756c746f',
'hello world': '68656c6c6f20776f726c64',
},
Bytes: {
test: new Uint8Array([0x74, 0x65, 0x73, 0x74]),
occulto: new Uint8Array([0x6f, 0x63, 0x63, 0x75, 0x6c, 0x74, 0x6f]),
'entropy is king': new Uint8Array([
0x65, 0x6e, 0x74, 0x72, 0x6f, 0x70, 0x79, 0x20, 0x69, 0x73, 0x20, 0x6b, 0x69, 0x6e, 0x67,
]),
},
}, },
Hash: { Hash: {
SHA_1: { SHA_1: {
@@ -39,6 +51,8 @@ export const Precomputed = {
}, },
Messages: { Messages: {
test: 'test', test: 'test',
occulto: 'occulto',
weird: 'Some 🃏 weird 🃏 text',
nietzscheIpsum: nietzscheIpsum:
'Marvelous intentions joy deceptions overcome sexuality spirit against. Selfish of marvelous play dead war snare eternal-return ultimate. Reason aversion suicide.', 'Marvelous intentions joy deceptions overcome sexuality spirit against. Selfish of marvelous play dead war snare eternal-return ultimate. Reason aversion suicide.',
}, },