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

feat(typescript): add ts declarations #3

Merged
merged 1 commit into from
Jan 27, 2024
Merged
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
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
node_modules/
dist/*
dist/*
.DS_Store
1 change: 1 addition & 0 deletions .npmignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@ coverage/
.husky/
e2e/
*.mjs
dist/.dts
4 changes: 2 additions & 2 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
dist/*.js
.github/workflows/*.yml
.github/workflows/*.yml
dist/*.js
5 changes: 2 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ const decrypted = await decryptFile(encrypted, privateKey);
## Background

The original use case for this library was a service that supported file uploads, but made these files public under a non-guessable link.
I consider this (security through obscurity)[https://en.wikipedia.org/wiki/Security_through_obscurity].
Encrypting the files added an extra layer of protection in case an URL is leaked accidentally or intentionally.

## How it works
Expand All @@ -33,11 +32,11 @@ The result is packed in the following format:

### Encryption

![Encryption schema](./doc/encrypt.png)
![Encryption schema](https://github.com/mojadev/simple-file-encryption/raw/main/doc/encrypt.png)

### Decryption

![Decryption schema](./doc/decrypt.png)
![Decryption schema](https://github.com/mojadev/simple-file-encryption/raw/main/doc/decrypt.png)

## Usage

Expand Down
6 changes: 6 additions & 0 deletions keys/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
The keys in this folder can be generated using `npm run genkeys`.
They are intentionally left here in the repository and are not used in any production environment.

Consider them as a reference in case you aren't sure how your keys should look.

The file [test is the private key](./test) while [test.pub is the public key](./test.pub).
40 changes: 40 additions & 0 deletions keys/test
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
-----BEGIN PRIVATE KEY-----
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
xp1SwhStmWkIu8HwAeZD3+YS
-----END PRIVATE KEY-----
11 changes: 11 additions & 0 deletions keys/test.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
-----BEGIN PUBLIC KEY-----
MIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEA66NtDN57eyOkvETZtZM6
d8+xn+7twk6SfzAMv78MGfI+MjHsVbFTDG4YT+NiXw29wyIs4AgXayT2hOfbi6yI
6v6SrNrpGwXUJtsgEauctJvnDYMZHT+ZtCZCKZjkoxOarO8TXBPcx1npsc6s0cQS
4JWFc71+rRDwHm/NHwXzjiHL/rXMqdI48rCszqVFR4JfrnCvCWq4MrZILocnngtc
Y1T+/1idaAbtYF2AcYogJy7j87Na8kTXwxRgbS/XWgLfWv1SrdJfmF+CY4Zw4hV0
+Hv+17Oz8WlOB5gnQ4RIQkCnydXN3Mc4pOGWm9E44t9kfUa8qG9a7qUo0ukr3NgW
T7fp9g2S5eDyaUX7UToLsNZuCigurkYFtsiGqaY673bq9snzTMM3qThzV8/7GuHp
ykVs0J9LUx3r5gyugpL1MuJLctdrkQy9NzFLq3rJnqK1I+oR2l9aon3Ynr/o8Cx/
Wwjr/OM9DsDyNYZDFtrM3kMYjr+53XZlmSAi0cOCsmApAgMBAAE=
-----END PUBLIC KEY-----
1 change: 1 addition & 0 deletions keys/test.pub
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDro20M3nt7I6S8RNm1kzp3z7Gf7u3CTpJ/MAy/vwwZ8j4yMexVsVMMbhhP42JfDb3DIizgCBdrJPaE59uLrIjq/pKs2ukbBdQm2yARq5y0m+cNgxkdP5m0JkIpmOSjE5qs7xNcE9zHWemxzqzRxBLglYVzvX6tEPAeb80fBfOOIcv+tcyp0jjysKzOpUVHgl+ucK8JargytkguhyeeC1xjVP7/WJ1oBu1gXYBxiiAnLuPzs1ryRNfDFGBtL9daAt9a/VKt0l+YX4JjhnDiFXT4e/7Xs7PxaU4HmCdDhEhCQKfJ1c3cxzik4Zab0Tji32R9Rryob1rupSjS6Svc2BZPt+n2DZLl4PJpRftROguw1m4KKC6uRgW2yIappjrvdur2yfNMwzepOHNXz/sa4enKRWzQn0tTHevmDK6CkvUy4kty12uRDL03MUuresmeorUj6hHaX1qifdiev+jwLH9bCOv84z0OwPI1hkMW2szeQxiOv7nddmWZICLRw4KyYCk= [email protected]
35 changes: 35 additions & 0 deletions package-lock.json

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

4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"version": "1.0.0",
"description": "Simple public/private key encryption and decryption of files in your browser using the WebCrypto API.",
"main": "dist/simple-file-encryption.js",
"module": "dist/simple-file-encryption.mjs",
"typings": "dist/simple-file-encryption.d.ts",
"scripts": {
"prebuild": "rimraf ./dist/*",
Expand Down Expand Up @@ -37,11 +38,12 @@
"husky": "^8.0.3",
"rimraf": "^5.0.5",
"rollup": "^4.9.4",
"rollup-plugin-dts": "^6.1.0",
"typescript": "^5.3.3"
},
"config": {
"commitizen": {
"path": "./node_modules/cz-conventional-changelog"
}
}
}
}
6 changes: 6 additions & 0 deletions rollup.config.mjs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import typescript from "@rollup/plugin-typescript";
import terser from "@rollup/plugin-terser";
import dts from "rollup-plugin-dts";

export default [
{
Expand Down Expand Up @@ -32,4 +33,9 @@ export default [
],
plugins: [typescript()],
},
{
input: "./dist/.dts/index.d.ts",
output: [{ file: "dist/simple-file-encryption.d.ts", format: "es" }],
plugins: [dts()],
},
];
6 changes: 6 additions & 0 deletions src/container.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,12 @@ export const packContainer = (
return result;
};

/**
* Unpack a string containing an encrypted file.
*
* @param payload The payload that should be unpacked
* @returns An object containing a key and the payload
*/
export const unpackContainer = (
payload: ContainerBuffer
): { key: KeyType; payload: EncryptedPayload } => {
Expand Down
6 changes: 3 additions & 3 deletions src/decrypt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ async function decryptPayload(
encryptedPayload: EncryptedPayload
) {
try {
return await window.crypto.subtle.decrypt(
return await globalThis.crypto.subtle.decrypt(
{
name: "AES-CBC",
iv,
Expand All @@ -57,7 +57,7 @@ async function decryptPayload(

async function createAESKey(aesSecret: Secret) {
try {
return await window.crypto.subtle.importKey(
return await globalThis.crypto.subtle.importKey(
"raw",
aesSecret,
{ name: "AES-CBC", length: 512 },
Expand All @@ -71,7 +71,7 @@ async function createAESKey(aesSecret: Secret) {

async function decryptAESSecret(key: PrivateKey, encryptedKey: KeyType) {
try {
return await window.crypto.subtle.decrypt(
return await globalThis.crypto.subtle.decrypt(
{
name: "RSA-OAEP",
},
Expand Down
22 changes: 21 additions & 1 deletion src/encrypt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,13 @@ import { packContainer } from "./container";
import { importPublicKey } from "./rsa-key";
import { AESKey, PlaintextPayload, PublicKeyPEMString, Secret } from "./types";

/**
* Encrypt the given file with the provided public key.
*
* @param file
* @param publicKey
* @returns
*/
export async function encryptFile(
file: File,
publicKey: PublicKeyPEMString
Expand All @@ -26,9 +33,15 @@ export async function encryptFile(
return new File([result], file.name, { type: file.type });
}

/**
* Encrypt the given buffer using the provided symmetric key.
*
* @param inlineKey the AESKey to use for encrypting
* @param buffer the buffer that should be encrypted
*/
async function encryptPayload(inlineKey: AESKey, buffer: PlaintextPayload) {
try {
const iv = window.crypto.getRandomValues(new Uint8Array(IV_LENGTH));
const iv = globalThis.crypto.getRandomValues(new Uint8Array(IV_LENGTH));
const encryptedPayload = await crypto.subtle.encrypt(
{ name: AES_ALGO, iv },
inlineKey,
Expand All @@ -40,6 +53,13 @@ async function encryptPayload(inlineKey: AESKey, buffer: PlaintextPayload) {
}
}

/**
* Generate a random symmetric key that can be used for encrypting and decrypting.
*
* The return type contains the CryptoKey and the ArrayBuffer for convenience.
*
* @returns A tuple containing the crypto key and it's raw (arraybuffer) representation
*/
async function generateSymmetricKey(): Promise<[AESKey, Secret]> {
try {
const cryptoKey = await crypto.subtle.generateKey(
Expand Down
5 changes: 4 additions & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@
"target": "es2016",
"module": "ESNext",
"esModuleInterop": true,
"declarationDir": ".dts",
"forceConsistentCasingInFileNames": true,
"strict": true,
"skipLibCheck": true
"skipLibCheck": true,
"declaration": true,
"declarationMap": true
}
}
Loading