Skip to content

Commit

Permalink
feat: update crypto and add actions
Browse files Browse the repository at this point in the history
  • Loading branch information
hungtcs committed Mar 14, 2024
1 parent 8db84cd commit bcee9db
Show file tree
Hide file tree
Showing 15 changed files with 174 additions and 191 deletions.
50 changes: 50 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
name: Tagged release

on:
push:
tags:
- "v*"

jobs:
check:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [20.x]
steps:
- uses: actions/checkout@v3
- uses: pnpm/action-setup@v3
with:
version: 8
- uses: actions/setup-node@v3
with:
cache: "pnpm"
node-version: ${{ matrix.node-version }}
- run: pnpm install
- run: pnpm test:node
- run: pnpm test:jsdom
release:
needs: check
runs-on: "ubuntu-latest"
steps:
- uses: "marvinpinto/action-automatic-releases@latest"
with:
repo_token: "${{ secrets.GITHUB_TOKEN }}"
prerelease: false
publish:
needs: release
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: pnpm/action-setup@v3
with:
version: 8
- uses: actions/setup-node@v3
with:
cache: "pnpm"
node-version: ${{ matrix.node-version }}
registry-url: "https://registry.npmjs.org"
- run: pnpm install
- run: pnpm publish --access public
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
28 changes: 28 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
name: Test

on:
push:
branches:
- master
pull_request:
branches:
- master

jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [18.x, 20.x]
steps:
- uses: actions/checkout@v3
- uses: pnpm/action-setup@v3
with:
version: 8
- uses: actions/setup-node@v3
with:
cache: "pnpm"
node-version: ${{ matrix.node-version }}
- run: pnpm install
- run: pnpm run test:node
- run: pnpm run test:jsdom
6 changes: 5 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
{
"editor.codeActionsOnSave": {
"source.organizeImports": "explicit"
}
},
"cSpell.words": [
"marvinpinto",
"typedarrays"
]
}
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# datadata sdk javascript

![Test Workflow Status](https://github.com/datadata-team/datadata-sdk-javascript/actions/workflows/test.yml/badge.svg)

javascript sdk for [datadata](https://www.datadata.com) platform.

Support browser, nodejs.
Expand Down
12 changes: 0 additions & 12 deletions index.html

This file was deleted.

9 changes: 0 additions & 9 deletions lib/api-key/api-key.service.test.ts

This file was deleted.

88 changes: 1 addition & 87 deletions lib/api-key/api-key.service.ts
Original file line number Diff line number Diff line change
@@ -1,89 +1,3 @@
import AES from "crypto-js/aes";
import Base64 from "crypto-js/enc-base64";
import Hex from "crypto-js/enc-hex";
import Utf8 from "crypto-js/enc-utf8";
import WordArray from "crypto-js/lib-typedarrays";
import MD5 from "crypto-js/md5";
import CFB from "crypto-js/mode-cfb";
import Pkcs7 from "crypto-js/pad-pkcs7";
import { BaseService } from "../common";

export class APIKeyService extends BaseService {
public static async encrypt(secretKey: string, payload: string) {
const iv = WordArray.random(16);
const key = MD5(secretKey);
const value = Utf8.parse(payload).clone().concat(MD5(payload));
// const value = Utf8.parse(payload);

console.log(value.sigBytes);

const encrypted = AES.encrypt(value, key, { iv: iv, mode: CFB, padding: Pkcs7 });

console.log({
a: MD5(payload),
b: iv.clone().concat(encrypted.ciphertext),
});

return iv.clone().concat(encrypted.ciphertext).toString(Hex);
}

public static async decrypt(secretKey: string, ciphertext: string) {
const key = MD5(secretKey);
const cipherData = Hex.parse(ciphertext);
const iv = WordArray.create(cipherData.words.slice(0, 4), 16);
const data = WordArray.create(cipherData.words.slice(4), cipherData.sigBytes - 16);
const decrypted = AES.decrypt(data.toString(Base64), key, { iv: iv, mode: CFB });

console.log({ decrypted });

return decrypted.toString(Utf8);
}
}

function CryptJsWordArrayToUint8Array(wordArray: WordArray) {
const l = wordArray.sigBytes;
const words = wordArray.words;
const result = new Uint8Array(l);
var i = 0 /*dst*/,
j = 0; /*src*/
while (true) {
// here i is a multiple of 4
if (i == l) break;
var w = words[j++];
result[i++] = (w & 0xff000000) >>> 24;
if (i == l) break;
result[i++] = (w & 0x00ff0000) >>> 16;
if (i == l) break;
result[i++] = (w & 0x0000ff00) >>> 8;
if (i == l) break;
result[i++] = w & 0x000000ff;
}
return result;
}

function hexStringToUint8Array(hexString: string) {
if (hexString.length % 2 !== 0) {
throw "Invalid hexString";
} /*from w w w. j av a 2s . c o m*/
var arrayBuffer = new Uint8Array(hexString.length / 2);

for (var i = 0; i < hexString.length; i += 2) {
var byteValue = parseInt(hexString.substr(i, 2), 16);
if (isNaN(byteValue)) {
throw "Invalid hexString";
}
arrayBuffer[i / 2] = byteValue;
}

return arrayBuffer;
}

function convertUint8ArrayToWordArray(u8Array: Uint8Array): WordArray {
var words = [],
i = 0,
len = u8Array.length;
while (i < len) {
words.push((u8Array[i++] << 24) | (u8Array[i++] << 16) | (u8Array[i++] << 8) | u8Array[i++]);
}
return WordArray.create(words, u8Array.length);
}
export class APIKeyService extends BaseService {}
10 changes: 10 additions & 0 deletions lib/api-key/crypto.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { test } from "vitest";
import { decrypt, encrypt } from "./crypto";

test("encrypt and decrypt", async (t) => {
const key = "500c33c5485e4d7eb5c89dd8f33084dc";
const data = `{ "uid": "001", "host": "www.example.com", "expired": 1741918889 }`;
const encrypted = await encrypt(key, data);
const decrypted = await decrypt(key, encrypted);
t.expect(decrypted).toEqual(data);
});
63 changes: 63 additions & 0 deletions lib/api-key/crypto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import AES from "crypto-js/aes";
import Base64 from "crypto-js/enc-base64";
import Hex from "crypto-js/enc-hex";
import Utf8 from "crypto-js/enc-utf8";
import WordArray from "crypto-js/lib-typedarrays";
import MD5 from "crypto-js/md5";
import CFB from "crypto-js/mode-cfb";
import Pkcs7 from "crypto-js/pad-pkcs7";

export async function encrypt(secretKey: string, payload: string) {
const iv = WordArray.random(16);
const key = MD5(secretKey);
const value = Utf8.parse(payload).clone().concat(MD5(payload));
const encrypted = AES.encrypt(value, key, { iv: iv, mode: CFB, padding: Pkcs7 });
return iv.clone().concat(encrypted.ciphertext).toString(Hex);
}

export async function decrypt(secretKey: string, encrypted: string) {
const key = MD5(secretKey);
const cipherData = Hex.parse(encrypted);
const iv = WordArray.create(cipherData.words.slice(0, 4), 16);
const data = WordArray.create(cipherData.words.slice(4), cipherData.sigBytes - 16);
const decrypted = AES.decrypt(data.toString(Base64), key, { iv: iv, mode: CFB, padding: Pkcs7 });
const dataPart = WordArray.create(decrypted.words.slice(0, -4), decrypted.sigBytes - 16);
const hashPart = uint8ArrayToWordArray(wordArrayToUint8Array(decrypted).slice(decrypted.sigBytes - 16));
const result = dataPart.toString(Utf8);

if (MD5(result).toString(Hex) !== hashPart.toString(Hex)) {
throw new Error("checksum invalid");
}
return result;
}

function wordArrayToUint8Array(wordArray: WordArray) {
const l = wordArray.sigBytes;
const words = wordArray.words;
const result = new Uint8Array(l);
var i = 0,
j = 0;
while (true) {
// here i is a multiple of 4
if (i == l) break;
var w = words[j++];
result[i++] = (w & 0xff000000) >>> 24;
if (i == l) break;
result[i++] = (w & 0x00ff0000) >>> 16;
if (i == l) break;
result[i++] = (w & 0x0000ff00) >>> 8;
if (i == l) break;
result[i++] = w & 0x000000ff;
}
return result;
}

function uint8ArrayToWordArray(u8Array: Uint8Array) {
var words = [],
i = 0,
len = u8Array.length;
while (i < len) {
words.push((u8Array[i++] << 24) | (u8Array[i++] << 16) | (u8Array[i++] << 8) | u8Array[i++]);
}
return WordArray.create(words, u8Array.length);
}
1 change: 1 addition & 0 deletions lib/api-key/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from "./api-key";
export * from "./api-key.service";
export * from "./api-token-payload";
export * from "./crypto";
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"module": "./dist/index.js",
"types": "./dist/index.d.ts",
"scripts": {
"dev": "vite",
"dev": "vite build --watch",
"test:node": "vitest --watch=false --environment=node",
"test:jsdom": "vitest --watch=false --environment=jsdom",
"build": "vite build",
Expand All @@ -26,7 +26,7 @@
"vite": "^5.1.6",
"vite-plugin-checker": "^0.6.4",
"vite-plugin-dts": "^3.7.3",
"vite-tsconfig-paths": "^4.3.1",
"vite-plugin-externalize-deps": "^0.8.0",
"vitest": "^1.3.1"
},
"dependencies": {
Expand Down
38 changes: 6 additions & 32 deletions pnpm-lock.yaml

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

Loading

0 comments on commit bcee9db

Please sign in to comment.