cas-typescript-sdk 1.0.10 → 1.0.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Cargo.toml +1 -0
- package/README.md +2 -0
- package/index.d.ts +11 -0
- package/index.node +0 -0
- package/lib/asymmetric/RSAWrapper.d.ts +8 -0
- package/lib/asymmetric/RSAWrapper.js +52 -0
- package/lib/asymmetric/index.d.ts +3 -0
- package/lib/asymmetric/index.js +7 -0
- package/lib/index.d.ts +2 -1
- package/lib/index.js +4 -1
- package/package.json +1 -1
- package/src/asymmetric/cas_asymmetric_encryption.rs +15 -0
- package/src/asymmetric/cas_rsa.rs +80 -0
- package/src/lib.rs +5 -0
- package/src-ts/asymmetric/RSAWrapper.ts +53 -0
- package/src-ts/asymmetric/index.ts +4 -0
- package/src-ts/index.ts +4 -1
- package/test-ts/asymmetric.test.spec.ts +28 -0
package/Cargo.toml
CHANGED
package/README.md
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# eas-typescript-sdk
|
|
2
2
|
|
|
3
|
+
Ever wanted all of your most useful cryptograpihc operations in one module and not have to surf documentation for various packages?
|
|
4
|
+
CAS is here to provide a unified development experience as an abstract layer to the RustCrypto and Dalek-Cryptography suite of algorithms.
|
|
3
5
|
The official NPM page can be found [here](https://www.npmjs.com/package/cas-typescript-sdk).
|
|
4
6
|
|
|
5
7
|
## Consuming Library Documentation
|
package/index.d.ts
CHANGED
|
@@ -22,9 +22,20 @@ export function aes128Encrypt(aesKey: Array<number>, nonce: Array<number>, plain
|
|
|
22
22
|
export function aes128Decrypt(aesKey: Array<number>, nonce: Array<number>, ciphertext: Array<number>): Array<number>
|
|
23
23
|
export function aes256Encrypt(aesKey: Array<number>, nonce: Array<number>, plaintext: Array<number>): Array<number>
|
|
24
24
|
export function aes256Decrypt(aesKey: Array<number>, nonce: Array<number>, ciphertext: Array<number>): Array<number>
|
|
25
|
+
export function generateRsaKeys(keySize: number): RsaKeyPairResult
|
|
26
|
+
export function encryptPlaintextRsa(publicKey: string, plaintext: Array<number>): Array<number>
|
|
27
|
+
export function decryptCiphertextRsa(privateKey: string, ciphertext: Array<number>): Array<number>
|
|
28
|
+
export function signRsa(privateKey: string, hash: Array<number>): Array<number>
|
|
29
|
+
export function verifyRsa(publicKey: string, hash: Array<number>, signature: Array<number>): boolean
|
|
25
30
|
export type x25519SecretPublicKeyResult = X25519SecretPublicKeyResult
|
|
26
31
|
export class X25519SecretPublicKeyResult {
|
|
27
32
|
publicKey: Array<number>
|
|
28
33
|
secretKey: Array<number>
|
|
29
34
|
constructor(publicKey: Array<number>, secretKey: Array<number>)
|
|
30
35
|
}
|
|
36
|
+
export type RSAKeyPairResult = RsaKeyPairResult
|
|
37
|
+
export class RsaKeyPairResult {
|
|
38
|
+
privateKey: string
|
|
39
|
+
publicKey: string
|
|
40
|
+
constructor(privateKey: string, publicKey: string)
|
|
41
|
+
}
|
package/index.node
CHANGED
|
Binary file
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { RsaKeyPairResult } from "../../index";
|
|
2
|
+
export declare class RSAWrapper {
|
|
3
|
+
generateKeys(keySize: number): RsaKeyPairResult;
|
|
4
|
+
encrypt(publicKey: string, plaintext: Array<number>): Array<number>;
|
|
5
|
+
decrypt(privateKey: string, ciphertext: Array<number>): Array<number>;
|
|
6
|
+
sign(privateKey: string, hash: Array<number>): Array<number>;
|
|
7
|
+
verify(publicKey: string, hash: Array<number>, signature: Array<number>): boolean;
|
|
8
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.RSAWrapper = void 0;
|
|
4
|
+
const index_1 = require("../../index");
|
|
5
|
+
class RSAWrapper {
|
|
6
|
+
generateKeys(keySize) {
|
|
7
|
+
if (keySize !== 1024 && keySize !== 2048 && keySize !== 4096) {
|
|
8
|
+
throw new Error("You must provide an appropriate key size to generate RSA keys");
|
|
9
|
+
}
|
|
10
|
+
return (0, index_1.generateRsaKeys)(keySize);
|
|
11
|
+
}
|
|
12
|
+
encrypt(publicKey, plaintext) {
|
|
13
|
+
if (!publicKey) {
|
|
14
|
+
throw new Error("You must provide a public key to encrypt with RSA");
|
|
15
|
+
}
|
|
16
|
+
if (!plaintext || plaintext.length === 0) {
|
|
17
|
+
throw new Error("You must provide an array of plaintext bytes to encrypt with RSA");
|
|
18
|
+
}
|
|
19
|
+
return (0, index_1.encryptPlaintextRsa)(publicKey, plaintext);
|
|
20
|
+
}
|
|
21
|
+
decrypt(privateKey, ciphertext) {
|
|
22
|
+
if (!privateKey) {
|
|
23
|
+
throw new Error("You must provide a private key to encrypt with RSA");
|
|
24
|
+
}
|
|
25
|
+
if (!ciphertext || ciphertext.length === 0) {
|
|
26
|
+
throw new Error("You must provide an array of ciphertext bytes to encrypt with RSA");
|
|
27
|
+
}
|
|
28
|
+
return (0, index_1.decryptCiphertextRsa)(privateKey, ciphertext);
|
|
29
|
+
}
|
|
30
|
+
sign(privateKey, hash) {
|
|
31
|
+
if (!privateKey) {
|
|
32
|
+
throw new Error("You must provide a private key to sign with RSA");
|
|
33
|
+
}
|
|
34
|
+
if (!hash || hash.length === 0) {
|
|
35
|
+
throw new Error("You must provide an allocated hash to sign with RSA");
|
|
36
|
+
}
|
|
37
|
+
return (0, index_1.signRsa)(privateKey, hash);
|
|
38
|
+
}
|
|
39
|
+
verify(publicKey, hash, signature) {
|
|
40
|
+
if (!publicKey) {
|
|
41
|
+
throw new Error("You must provide a public key to verify with RSA");
|
|
42
|
+
}
|
|
43
|
+
if (!hash || hash.length === 0) {
|
|
44
|
+
throw new Error("You must provide an allocated hash to verify with RSA");
|
|
45
|
+
}
|
|
46
|
+
if (!signature || signature.length === 0) {
|
|
47
|
+
throw new Error("You must provide and allocated signature to verify with RSA");
|
|
48
|
+
}
|
|
49
|
+
return (0, index_1.verifyRsa)(publicKey, hash, signature);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
exports.RSAWrapper = RSAWrapper;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.RsaKeyPairResult = exports.RSAWrapper = void 0;
|
|
4
|
+
const RSAWrapper_1 = require("./RSAWrapper");
|
|
5
|
+
Object.defineProperty(exports, "RSAWrapper", { enumerable: true, get: function () { return RSAWrapper_1.RSAWrapper; } });
|
|
6
|
+
const index_1 = require("../../index");
|
|
7
|
+
Object.defineProperty(exports, "RsaKeyPairResult", { enumerable: true, get: function () { return index_1.RsaKeyPairResult; } });
|
package/lib/index.d.ts
CHANGED
|
@@ -2,4 +2,5 @@ import { Argon2Wrapper, BCryptWrapper, PasswordHasherFactory, PasswordHasherType
|
|
|
2
2
|
import { HasherFactory, HasherType, SHAWrapper } from "./hashers/index";
|
|
3
3
|
import { X25519Wrapper } from "./key_exchange/index";
|
|
4
4
|
import { AESWrapper } from "./symmetric/index";
|
|
5
|
-
|
|
5
|
+
import { RSAWrapper, RsaKeyPairResult } from "./asymmetric";
|
|
6
|
+
export { Argon2Wrapper, BCryptWrapper, HasherFactory, HasherType, PasswordHasherFactory, PasswordHasherType, ScryptWrapper, SHAWrapper, X25519Wrapper, AESWrapper, RSAWrapper, RsaKeyPairResult };
|
package/lib/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.AESWrapper = exports.X25519Wrapper = exports.SHAWrapper = exports.ScryptWrapper = exports.PasswordHasherType = exports.PasswordHasherFactory = exports.HasherType = exports.HasherFactory = exports.BCryptWrapper = exports.Argon2Wrapper = void 0;
|
|
3
|
+
exports.RsaKeyPairResult = exports.RSAWrapper = exports.AESWrapper = exports.X25519Wrapper = exports.SHAWrapper = exports.ScryptWrapper = exports.PasswordHasherType = exports.PasswordHasherFactory = exports.HasherType = exports.HasherFactory = exports.BCryptWrapper = exports.Argon2Wrapper = void 0;
|
|
4
4
|
const index_1 = require("./password-hashers/index");
|
|
5
5
|
Object.defineProperty(exports, "Argon2Wrapper", { enumerable: true, get: function () { return index_1.Argon2Wrapper; } });
|
|
6
6
|
Object.defineProperty(exports, "BCryptWrapper", { enumerable: true, get: function () { return index_1.BCryptWrapper; } });
|
|
@@ -15,3 +15,6 @@ const index_3 = require("./key_exchange/index");
|
|
|
15
15
|
Object.defineProperty(exports, "X25519Wrapper", { enumerable: true, get: function () { return index_3.X25519Wrapper; } });
|
|
16
16
|
const index_4 = require("./symmetric/index");
|
|
17
17
|
Object.defineProperty(exports, "AESWrapper", { enumerable: true, get: function () { return index_4.AESWrapper; } });
|
|
18
|
+
const asymmetric_1 = require("./asymmetric");
|
|
19
|
+
Object.defineProperty(exports, "RSAWrapper", { enumerable: true, get: function () { return asymmetric_1.RSAWrapper; } });
|
|
20
|
+
Object.defineProperty(exports, "RsaKeyPairResult", { enumerable: true, get: function () { return asymmetric_1.RsaKeyPairResult; } });
|
package/package.json
CHANGED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
use napi_derive::napi;
|
|
2
|
+
|
|
3
|
+
#[napi(constructor)]
|
|
4
|
+
pub struct RSAKeyPairResult {
|
|
5
|
+
pub private_key: String,
|
|
6
|
+
pub public_key: String
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
pub trait CASRSAEncryption {
|
|
10
|
+
fn generate_rsa_keys(key_size: u32) -> RSAKeyPairResult;
|
|
11
|
+
fn encrypt_plaintext(public_key: String, plaintext: Vec<u8>) -> Vec<u8>;
|
|
12
|
+
fn decrypt_ciphertext(private_key: String, ciphertext: Vec<u8>) -> Vec<u8>;
|
|
13
|
+
fn sign(private_key: String, hash: Vec<u8>) -> Vec<u8>;
|
|
14
|
+
fn verify(public_key: String, hash: Vec<u8>, signed_text: Vec<u8>) -> bool;
|
|
15
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
use napi_derive::napi;
|
|
2
|
+
use rand::rngs::OsRng;
|
|
3
|
+
use rsa::{
|
|
4
|
+
pkcs1::{DecodeRsaPublicKey, EncodeRsaPublicKey}, pkcs8::{DecodePrivateKey, EncodePrivateKey}, Pkcs1v15Encrypt, Pkcs1v15Sign, RsaPrivateKey, RsaPublicKey
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
use super::cas_asymmetric_encryption::{CASRSAEncryption, RSAKeyPairResult};
|
|
8
|
+
pub struct CASRSA;
|
|
9
|
+
|
|
10
|
+
impl CASRSAEncryption for CASRSA {
|
|
11
|
+
fn generate_rsa_keys(key_size: u32) -> RSAKeyPairResult {
|
|
12
|
+
let mut rng: OsRng = OsRng;
|
|
13
|
+
let private_key: RsaPrivateKey = RsaPrivateKey::new(&mut rng, key_size as usize).expect("failed to generate a key");
|
|
14
|
+
let public_key: RsaPublicKey = private_key.to_public_key();
|
|
15
|
+
let result = RSAKeyPairResult {
|
|
16
|
+
public_key: public_key.to_pkcs1_pem(rsa::pkcs1::LineEnding::LF).unwrap().to_string(),
|
|
17
|
+
private_key: private_key.to_pkcs8_pem(rsa::pkcs8::LineEnding::LF).unwrap().to_string()
|
|
18
|
+
};
|
|
19
|
+
result
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
fn encrypt_plaintext(public_key: String, plaintext: Vec<u8>) -> Vec<u8> {
|
|
23
|
+
let public_key = RsaPublicKey::from_pkcs1_pem(&public_key).unwrap();
|
|
24
|
+
let mut rng = rand::thread_rng();
|
|
25
|
+
let ciphertext = public_key.encrypt(&mut rng, Pkcs1v15Encrypt, &plaintext).unwrap();
|
|
26
|
+
ciphertext
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
fn decrypt_ciphertext(private_key: String, ciphertext: Vec<u8>) -> Vec<u8> {
|
|
30
|
+
let private_key = RsaPrivateKey::from_pkcs8_pem(&private_key).unwrap();
|
|
31
|
+
let plaintext = private_key.decrypt(Pkcs1v15Encrypt, &ciphertext).unwrap();
|
|
32
|
+
plaintext
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
fn sign(private_key: String, hash: Vec<u8>) -> Vec<u8> {
|
|
36
|
+
let private_key = RsaPrivateKey::from_pkcs8_pem(&private_key).unwrap();
|
|
37
|
+
let mut signed_data = private_key.sign(Pkcs1v15Sign::new_unprefixed(), &hash).unwrap();
|
|
38
|
+
signed_data
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
fn verify(public_key: String, hash: Vec<u8>, signature: Vec<u8>) -> bool {
|
|
42
|
+
let public_key = RsaPublicKey::from_pkcs1_pem(&public_key).unwrap();
|
|
43
|
+
let verified = public_key.verify(
|
|
44
|
+
Pkcs1v15Sign::new_unprefixed(),
|
|
45
|
+
&hash,
|
|
46
|
+
&signature,
|
|
47
|
+
);
|
|
48
|
+
if verified.is_err() == false {
|
|
49
|
+
return true;
|
|
50
|
+
} else {
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
#[napi]
|
|
58
|
+
pub fn generate_rsa_keys(key_size: u32) -> RSAKeyPairResult {
|
|
59
|
+
return CASRSA::generate_rsa_keys(key_size);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
#[napi]
|
|
63
|
+
pub fn encrypt_plaintext_rsa(public_key: String, plaintext: Vec<u8>) -> Vec<u8> {
|
|
64
|
+
return CASRSA::encrypt_plaintext(public_key, plaintext);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
#[napi]
|
|
68
|
+
pub fn decrypt_ciphertext_rsa(private_key: String, ciphertext: Vec<u8>) -> Vec<u8> {
|
|
69
|
+
return CASRSA::decrypt_ciphertext(private_key, ciphertext);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
#[napi]
|
|
73
|
+
pub fn sign_rsa(private_key: String, hash: Vec<u8>) -> Vec<u8> {
|
|
74
|
+
return CASRSA::sign(private_key, hash);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
#[napi]
|
|
78
|
+
pub fn verify_rsa(public_key: String, hash: Vec<u8>, signature: Vec<u8>) -> bool {
|
|
79
|
+
return CASRSA::verify(public_key, hash, signature);
|
|
80
|
+
}
|
package/src/lib.rs
CHANGED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { decryptCiphertextRsa, encryptPlaintextRsa, generateRsaKeys, RsaKeyPairResult, signRsa, verifyRsa } from "../../index";
|
|
2
|
+
|
|
3
|
+
export class RSAWrapper {
|
|
4
|
+
public generateKeys(keySize: number): RsaKeyPairResult {
|
|
5
|
+
if (keySize !== 1024 && keySize !== 2048 && keySize !== 4096) {
|
|
6
|
+
throw new Error("You must provide an appropriate key size to generate RSA keys");
|
|
7
|
+
}
|
|
8
|
+
return generateRsaKeys(keySize);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
public encrypt(publicKey: string, plaintext: Array<number>): Array<number> {
|
|
12
|
+
if (!publicKey) {
|
|
13
|
+
throw new Error("You must provide a public key to encrypt with RSA");
|
|
14
|
+
}
|
|
15
|
+
if (!plaintext || plaintext.length === 0) {
|
|
16
|
+
throw new Error("You must provide an array of plaintext bytes to encrypt with RSA");
|
|
17
|
+
}
|
|
18
|
+
return encryptPlaintextRsa(publicKey, plaintext);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
public decrypt(privateKey: string, ciphertext: Array<number>): Array<number> {
|
|
22
|
+
if (!privateKey) {
|
|
23
|
+
throw new Error("You must provide a private key to encrypt with RSA");
|
|
24
|
+
}
|
|
25
|
+
if (!ciphertext || ciphertext.length === 0) {
|
|
26
|
+
throw new Error("You must provide an array of ciphertext bytes to encrypt with RSA");
|
|
27
|
+
}
|
|
28
|
+
return decryptCiphertextRsa(privateKey, ciphertext);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
public sign(privateKey: string, hash: Array<number>): Array<number> {
|
|
32
|
+
if (!privateKey) {
|
|
33
|
+
throw new Error("You must provide a private key to sign with RSA");
|
|
34
|
+
}
|
|
35
|
+
if (!hash || hash.length === 0) {
|
|
36
|
+
throw new Error("You must provide an allocated hash to sign with RSA");
|
|
37
|
+
}
|
|
38
|
+
return signRsa(privateKey, hash);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
public verify(publicKey: string, hash: Array<number>, signature: Array<number>): boolean {
|
|
42
|
+
if (!publicKey) {
|
|
43
|
+
throw new Error("You must provide a public key to verify with RSA");
|
|
44
|
+
}
|
|
45
|
+
if (!hash || hash.length === 0) {
|
|
46
|
+
throw new Error("You must provide an allocated hash to verify with RSA");
|
|
47
|
+
}
|
|
48
|
+
if (!signature || signature.length === 0) {
|
|
49
|
+
throw new Error("You must provide and allocated signature to verify with RSA");
|
|
50
|
+
}
|
|
51
|
+
return verifyRsa(publicKey, hash, signature);
|
|
52
|
+
}
|
|
53
|
+
}
|
package/src-ts/index.ts
CHANGED
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
import { HasherFactory, HasherType, SHAWrapper } from "./hashers/index";
|
|
9
9
|
import { X25519Wrapper } from "./key_exchange/index";
|
|
10
10
|
import { AESWrapper } from "./symmetric/index";
|
|
11
|
+
import { RSAWrapper, RsaKeyPairResult } from "./asymmetric";
|
|
11
12
|
|
|
12
13
|
export {
|
|
13
14
|
Argon2Wrapper,
|
|
@@ -19,5 +20,7 @@ export {
|
|
|
19
20
|
ScryptWrapper,
|
|
20
21
|
SHAWrapper,
|
|
21
22
|
X25519Wrapper,
|
|
22
|
-
AESWrapper
|
|
23
|
+
AESWrapper,
|
|
24
|
+
RSAWrapper,
|
|
25
|
+
RsaKeyPairResult
|
|
23
26
|
};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { assert } from "chai";
|
|
2
|
+
import { RSAWrapper, RsaKeyPairResult } from "..";
|
|
3
|
+
import { areEqual } from "./helpers/array";
|
|
4
|
+
|
|
5
|
+
describe("Asymmetric Tests", () => {
|
|
6
|
+
it("RSA 4096 encrypt and decrypt equals", () => {
|
|
7
|
+
const rsaWrapper: RSAWrapper = new RSAWrapper();
|
|
8
|
+
const keys: RsaKeyPairResult = rsaWrapper.generateKeys(4096);
|
|
9
|
+
const tohashed: string = "This is my array to encrypt";
|
|
10
|
+
const encoder = new TextEncoder();
|
|
11
|
+
const tohashBytes: Array<number> = Array.from(encoder.encode(tohashed));
|
|
12
|
+
const ciphertext = rsaWrapper.encrypt(keys.publicKey, tohashBytes);
|
|
13
|
+
const plaintext = rsaWrapper.decrypt(keys.privateKey, ciphertext);
|
|
14
|
+
let result = areEqual(tohashBytes, plaintext);
|
|
15
|
+
assert.isTrue(result);
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
it("RSA 2048 Sign and Verify", () => {
|
|
19
|
+
const rsaWrapper = new RSAWrapper();
|
|
20
|
+
const keys: RsaKeyPairResult = rsaWrapper.generateKeys(2048);
|
|
21
|
+
const tohashed: string = "This is my encrypt";
|
|
22
|
+
const encoder = new TextEncoder();
|
|
23
|
+
const toSignBytes: Array<number> = Array.from(encoder.encode(tohashed));
|
|
24
|
+
const signature: Array<number> = rsaWrapper.sign(keys.privateKey, toSignBytes);
|
|
25
|
+
const verified = rsaWrapper.verify(keys.publicKey, toSignBytes, signature);
|
|
26
|
+
assert.isTrue(verified);
|
|
27
|
+
});
|
|
28
|
+
});
|