Skip to content

Commit

Permalink
'import' syntax compatible and TypeScript declaration file (#1038)
Browse files Browse the repository at this point in the history
* exports

* Add TypeScript declaration file (index.d.ts)

* Add example for TypeScript

* Add flow for NodeJS with Typescript example

* CHANGELOG.md updated

* added import_module.mjs and test

* downgrade typescript to 4.4 to be compatible with node 12

* update workflow
  • Loading branch information
radetsky committed Nov 28, 2023
1 parent e924f76 commit 26665c0
Show file tree
Hide file tree
Showing 15 changed files with 387 additions and 3 deletions.
60 changes: 60 additions & 0 deletions .github/workflows/test-nodejs.yaml
Expand Up @@ -5,6 +5,7 @@ on:
paths:
- '.github/workflows/test-nodejs.yaml'
- 'docs/examples/js/**'
- 'docs/examples/ts/**'
- 'src/soter/**'
- 'src/themis/**'
- 'src/wrappers/themis/jsthemis/**'
Expand Down Expand Up @@ -132,3 +133,62 @@ jobs:
node secure_comparator_client.js
kill -SIGTERM "$!"
echo "ok"
- name: Test 'import' syntax
if: always()
run: |
cd $GITHUB_WORKSPACE/docs/examples/js/
echo "Test import syntax..."
node import_module.mjs
echo "ok"
- name: Install Typescript deps
if: always()
run: |
cd $GITHUB_WORKSPACE/docs/examples/ts/
npm install
npm run compile
- name: Test Typescript examples (Secure Keygen)
if: always()
run: |
cd $GITHUB_WORKSPACE/docs/examples/ts
echo "Test Secure Keygen..."
node secure_keygen.js
echo "ok"
- name: Test Typescript examples (Secure Cell)
if: always()
run: |
cd $GITHUB_WORKSPACE/docs/examples/ts
echo "Test Secure Cell..."
node secure_cell.js
echo "ok"
- name: Test Typescript examples (Secure Message)
if: always()
run: |
cd $GITHUB_WORKSPACE/docs/examples/ts
echo "Test Secure Message..."
alice=($(node secure_keygen.js | cut -c 15-))
bob=($(node secure_keygen.js | cut -c 15-))
enc=$(node secure_message.js enc "${alice[1]}" "${bob[2]}" message)
dec=$(node secure_message.js dec "${bob[1]}" "${alice[2]}" "$enc")
test "$dec" = "message"
echo "ok"
- name: Test Typescript examples (Secure Session)
if: always()
run: |
cd $GITHUB_WORKSPACE/docs/examples/ts
echo "Test Secure Session..."
node secure_session_server.js &
sleep 1 # give the server time to launch
node secure_session_client.js > output.txt
kill -SIGTERM "$!"
grep -q 'Hello server!!!' output.txt
echo "ok"
- name: Test Typescript examples (Secure Comparator)
if: always()
run: |
cd $GITHUB_WORKSPACE/docs/examples/ts
echo "Test Secure Comparator..."
node secure_comparator_server.js &
sleep 1 # give the server time to launch
node secure_comparator_client.js
kill -SIGTERM "$!"
echo "ok"
6 changes: 5 additions & 1 deletion CHANGELOG.md
Expand Up @@ -4,7 +4,11 @@

Changes that are currently in development and have not been released yet.

## [0.15.2](https://github.com/cossacklabs/themis/releases/tag/0.15.2), October 03 2023
## [0.15.2](https://github.com/cossacklabs/themis/releases/tag/0.15.2), November 24 2023

### JsThemis wrapper
- Added the ability to use the `import` syntax for the jsthemis module.
- Added a declaration file for TypeScript.

### Android, ReactNative wrappers
Updated versions of dependencies. New minimum versions of iOS, Android are set.
Expand Down
11 changes: 11 additions & 0 deletions docs/examples/js/import_module.mjs
@@ -0,0 +1,11 @@
import themis from 'jsthemis';
const { SymmetricKey, KeyPair} = themis;

let masterKey = new SymmetricKey()
console.log(masterKey);

let keypair = new KeyPair()
let privateKey = keypair.private()
let publicKey = keypair.public()
console.log(privateKey);
console.log(publicKey);
35 changes: 35 additions & 0 deletions docs/examples/ts/README.md
@@ -0,0 +1,35 @@
# Examples for JsThemis using TypeScript

## Install
```
git clone https://github.com/cossacklabs/themis.git
cd docs/examples/ts
npm install
```

## Compile
```
npm run compile
```
The command will compile TypeScript code into Javascript.

## Run
```
node ./secure_keygen.js
node ./secure_cell.js
node ./secure_message.js enc private1 public2 message
node ./secure_message.js dec private2 public1 message
node ./secure_comparator_server.js
node ./secure_comparator_client.js
node ./secure_session_server.js
node ./secure_session_client.js
```
`private1, private2, public1, public2` is the keys which can be generated by `secure_keygen.js`

Just run command by command to see how examples work.

## Clean
```
npm run clean
```
The command will delete all compiled JS files.
17 changes: 17 additions & 0 deletions docs/examples/ts/package.json
@@ -0,0 +1,17 @@
{
"name": "ts_examples_themis",
"version": "1.0.0",
"description": "",
"main": "secure_keygen.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"clean": "rm *.js",
"compile": "find . -maxdepth 1 -type f -name '*.ts' -exec ./node_modules/.bin/tsc {} \\;"
},
"author": "",
"license": "ISC",
"dependencies": {
"@types/node": "^20.9.5",
"typescript": "^4.4"
}
}
49 changes: 49 additions & 0 deletions docs/examples/ts/secure_cell.ts
@@ -0,0 +1,49 @@
import { SecureCellSeal, SecureCellTokenProtect, SecureCellContextImprint } from "jsthemis"

const message = Buffer.from('Test Message Please Ignore', 'utf-8')
const context = Buffer.from('Secure Cell example code','utf-8')
const master_key = Buffer.from('bm8sIHRoaXMgaXMgbm90IGEgdmFsaWQgbWFzdGVyIGtleQ==', 'base64')
const passphrase = 'My Litte Secret: Passphrase Is Magic'

console.log('# Secure Cell in Seal mode\n')
console.log('## Master key API\n')
const scellMK = SecureCellSeal.withKey(master_key)
const encrypted_message = scellMK.encrypt(message)
console.log('Encrypted: ' + Buffer.from(encrypted_message).toString('base64'))
const decrypted_message = scellMK.decrypt(encrypted_message)
console.log('Decrypted: ' + Buffer.from(decrypted_message).toString())
console.log()

const encrypted_message2 = Buffer.from('AAEBQAwAAAAQAAAAEQAAAC0fCd2mOIxlDUORXz8+qCKuHCXcDii4bMF8OjOCOqsKEdV4+Ga2xTHPMupFvg==', 'base64')
const decrypted_message2 = scellMK.decrypt(encrypted_message2)
console.log('Decrypted (simulator): ' + Buffer.from(decrypted_message2).toString())
console.log()
console.log('## Passphrase API\n')

const scellPW = SecureCellSeal.withPassphrase(passphrase)
const encrypted_message3 = scellPW.encrypt(message)
console.log('Encrypted: ' + Buffer.from(encrypted_message3).toString('base64'))
const decrypted_message3 = scellPW.decrypt(encrypted_message3)
console.log('Decrypted: ' + Buffer.from(decrypted_message3).toString())
console.log()

console.log('# Secure Cell in Token Protect mode\n')

const scellTP = SecureCellTokenProtect.withKey(master_key)
const encrypted_message4 = scellTP.encrypt(message)
console.log('Encrypted: ' + Buffer.from(encrypted_message4.data).toString('base64'))
console.log('Auth token: ' + Buffer.from(encrypted_message4.token).toString('base64'))
const decrypted_message4 = scellTP.decrypt(encrypted_message4.data, encrypted_message4.token)
console.log('Decrypted: ' + Buffer.from(decrypted_message4).toString())
console.log('')

console.log('# Secure Cell in Context Imprint mode\n')
const scellCI = SecureCellContextImprint.withKey(master_key)
const encrypted_message5 = scellCI.encrypt(message, context)
console.log('Encrypted: ' + Buffer.from(encrypted_message5).toString('base64'))
const decrypted_message5 = scellCI.decrypt(encrypted_message5, context)
console.log('Decrypted: ' + Buffer.from(decrypted_message5).toString())
console.log('')
console.log('SecureCell example code finished')


24 changes: 24 additions & 0 deletions docs/examples/ts/secure_comparator_client.ts
@@ -0,0 +1,24 @@
import { Socket } from 'net';
import { SecureComparator } from 'jsthemis';

const comparator = new SecureComparator(Buffer.from("secret"));

const client = new Socket();
client.connect(1337, '127.0.0.1', () => {
console.log('Connected');
client.write(comparator.beginCompare());
});

client.on('data', (data: Buffer) => {
const d = comparator.proceedCompare(data);
if (!comparator.isCompareComplete()) {
client.write(d);
} else {
console.log(comparator.isMatch());
client.destroy();
}
});

client.on('close', () => {
console.log('Connection closed');
});
17 changes: 17 additions & 0 deletions docs/examples/ts/secure_comparator_server.ts
@@ -0,0 +1,17 @@
import { createServer, Socket } from 'net';
import { SecureComparator } from 'jsthemis';

const server = createServer((socket: Socket) => {
const comparator = new SecureComparator(Buffer.from("secret"));

socket.on('data', (data: Buffer) => {
const d = comparator.proceedCompare(data);
socket.write(d);
if (comparator.isCompareComplete()) {
console.log(comparator.isMatch());
socket.destroy();
}
});
});

server.listen(1337, '127.0.0.1');
8 changes: 8 additions & 0 deletions docs/examples/ts/secure_keygen.ts
@@ -0,0 +1,8 @@
import { KeyPair, SymmetricKey } from 'jsthemis';

const masterKey = new SymmetricKey() as Uint8Array;
console.log("master key: ", Buffer.from(masterKey).toString("base64"));

const keypair = new KeyPair();
console.log("private key: ", Buffer.from(keypair.private()).toString("base64"));
console.log("public key : ", Buffer.from(keypair.public()).toString("base64"));
22 changes: 22 additions & 0 deletions docs/examples/ts/secure_message.ts
@@ -0,0 +1,22 @@
import { SecureMessage } from 'jsthemis';

if (process.argv.length == 6) {
const command = process.argv[2];
const private_key = process.argv[3];
const peer_public_key = process.argv[4];
const secure_message = new SecureMessage(
Buffer.from(private_key, "base64"),
Buffer.from(peer_public_key, "base64"));

if (command == "enc") {
const encrypted_message = secure_message.encrypt(Buffer.from(process.argv[5]));
console.log(Buffer.from(encrypted_message).toString("base64"));
} else if (command == "dec") {
const decrypted_message = secure_message.decrypt(Buffer.from(process.argv[5], "base64"));
console.log(Buffer.from(decrypted_message).toString("utf8"));
} else {
console.log("usage node secure_message.js <enc/dec> <private key> <peer public key> <message>");
}
} else {
console.log("usage node secure_message.js <enc/dec> <private key> <peer public key> <message>");
}
43 changes: 43 additions & 0 deletions docs/examples/ts/secure_session_client.ts
@@ -0,0 +1,43 @@
import { Socket } from 'net';
import { SecureSession } from 'jsthemis';

const session = new SecureSession(
Buffer.from("client"),
Buffer.from("UkVDMgAAAC3DZR2qAEbvO092R/IKXBttnf9dVSU65R+Fb4eNoyxxlzn2n4GR", "base64"),
(id: Uint8Array) => {
if (id.toString() === "server") {
return Buffer.from("VUVDMgAAAC30/vs+AwciK6egi82A9TkTydVuOzMFsJ9AkA0gMGyNH0tSu5Bk", "base64");
} else if (id.toString() === "client") {
return Buffer.from("VUVDMgAAAC15KNjgAr1DQEw+So1oztUarO4Jw/CGgyehBRCbOxbpHrPBKO7s", "base64");
}
return null;
}
);

let retry_count = 5;

const client: Socket = new Socket();
client.connect(1337, '127.0.0.1', () => {
console.log('Connected');
client.write(session.connectRequest());
});

client.on('data', (data: Buffer) => {
const d = session.unwrap(data);
if (!session.isEstablished()) {
client.write(d);
} else {
if (d !== undefined) {
console.log(d.toString());
}
if (retry_count--) {
client.write(session.wrap(Buffer.from("Hello server!!!")));
} else {
client.destroy();
}
}
});

client.on('close', () => {
console.log('Connection closed');
});
30 changes: 30 additions & 0 deletions docs/examples/ts/secure_session_server.ts
@@ -0,0 +1,30 @@
import { createServer, Socket } from 'net';
import { SecureSession } from 'jsthemis';

const server = createServer((socket: Socket) => {
const session = new SecureSession(
Buffer.from("server"),
Buffer.from("UkVDMgAAAC0U6AK7AAm6ha0cgHmovSTpZax01+icg9xwFlZAqqGWeGTqbHUt", "base64"),
(id: Uint8Array) => {
if (id.toString() === "server") {
return Buffer.from("VUVDMgAAAC30/vs+AwciK6egi82A9TkTydVuOzMFsJ9AkA0gMGyNH0tSu5Bk", "base64");
} else if (id.toString() === "client") {
return Buffer.from("VUVDMgAAAC15KNjgAr1DQEw+So1oztUarO4Jw/CGgyehBRCbOxbpHrPBKO7s", "base64");
}
return null;
}
);

socket.on('data', (data: Buffer) => {
if (!session.isEstablished()) {
const d = session.unwrap(data);
socket.write(d);
} else {
const d = session.unwrap(data);
console.log(d.toString());
socket.write(session.wrap(d));
}
});
});

server.listen(1337, '127.0.0.1');

0 comments on commit 26665c0

Please sign in to comment.