@twin.org/crypto 0.0.2-next.3 → 0.0.2-next.4
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/dist/cjs/index.cjs +116 -39
- package/dist/esm/index.mjs +117 -40
- package/dist/types/ciphers/rsa.d.ts +23 -11
- package/docs/changelog.md +18 -0
- package/docs/reference/classes/RSA.md +54 -58
- package/locales/en.json +1 -1
- package/package.json +4 -3
package/dist/cjs/index.cjs
CHANGED
|
@@ -726,6 +726,16 @@ class RSA {
|
|
|
726
726
|
* @internal
|
|
727
727
|
*/
|
|
728
728
|
static _CLASS_NAME = "RSA";
|
|
729
|
+
/**
|
|
730
|
+
* The public key for encryption.
|
|
731
|
+
* @internal
|
|
732
|
+
*/
|
|
733
|
+
_publicKeyBytes;
|
|
734
|
+
/**
|
|
735
|
+
* The private key for decryption.
|
|
736
|
+
* @internal
|
|
737
|
+
*/
|
|
738
|
+
_privateKeyBytes;
|
|
729
739
|
/**
|
|
730
740
|
* The public key for encryption.
|
|
731
741
|
* @internal
|
|
@@ -753,37 +763,15 @@ class RSA {
|
|
|
753
763
|
*/
|
|
754
764
|
constructor(publicKey, privateKey) {
|
|
755
765
|
core.Guards.uint8Array(RSA._CLASS_NAME, "publicKey", publicKey);
|
|
756
|
-
this.
|
|
757
|
-
|
|
758
|
-
format: "der",
|
|
759
|
-
type: "spki"
|
|
760
|
-
});
|
|
761
|
-
if (!core.Is.empty(privateKey)) {
|
|
762
|
-
this._privateKey = node_crypto.createPrivateKey({
|
|
763
|
-
key: Buffer.from(privateKey),
|
|
764
|
-
format: "der",
|
|
765
|
-
type: "pkcs8"
|
|
766
|
-
});
|
|
767
|
-
}
|
|
768
|
-
// Get modulus length in bits from key details
|
|
769
|
-
const modulusLengthBits = this._publicKey.asymmetricKeyDetails?.modulusLength;
|
|
770
|
-
if (core.Is.empty(modulusLengthBits)) {
|
|
771
|
-
throw new core.GeneralError(RSA._CLASS_NAME, "invalidKeySize");
|
|
772
|
-
}
|
|
773
|
-
// Convert bits to bytes
|
|
774
|
-
this._keySize = Math.ceil(modulusLengthBits / 8);
|
|
775
|
-
// Calculate block size for OAEP with SHA-256
|
|
776
|
-
// Formula: keySize - 2 * hashLength - 2
|
|
777
|
-
const hashLength = 32; // SHA-256 = 32 bytes
|
|
778
|
-
// eslint-disable-next-line no-mixed-operators
|
|
779
|
-
this._blockSize = this._keySize - 2 * hashLength - 2;
|
|
766
|
+
this._publicKeyBytes = publicKey;
|
|
767
|
+
this._privateKeyBytes = privateKey;
|
|
780
768
|
}
|
|
781
769
|
/**
|
|
782
770
|
* Generate a new RSA key pair in PKCS8 format.
|
|
783
771
|
* @param modulusLength The key size in bits (default: 2048).
|
|
784
772
|
* @returns The public and private keys as Uint8Array.
|
|
785
773
|
*/
|
|
786
|
-
static generateKeyPair(modulusLength = 2048) {
|
|
774
|
+
static async generateKeyPair(modulusLength = 2048) {
|
|
787
775
|
const { publicKey, privateKey } = node_crypto.generateKeyPairSync("rsa", {
|
|
788
776
|
modulusLength,
|
|
789
777
|
publicKeyEncoding: {
|
|
@@ -805,7 +793,7 @@ class RSA {
|
|
|
805
793
|
* @param pkcs1Key The PKCS1 key as Uint8Array.
|
|
806
794
|
* @returns The PKCS8 key as Uint8Array.
|
|
807
795
|
*/
|
|
808
|
-
static convertPkcs1ToPkcs8(pkcs1Key) {
|
|
796
|
+
static async convertPkcs1ToPkcs8(pkcs1Key) {
|
|
809
797
|
core.Guards.uint8Array(RSA._CLASS_NAME, "pkcs1Key", pkcs1Key);
|
|
810
798
|
const privateKey = node_crypto.createPrivateKey({
|
|
811
799
|
key: Buffer.from(pkcs1Key),
|
|
@@ -822,7 +810,7 @@ class RSA {
|
|
|
822
810
|
* @param pkcs8Key The PKCS8 key as Uint8Array.
|
|
823
811
|
* @returns The key components.
|
|
824
812
|
*/
|
|
825
|
-
static getPrivateKeyComponents(pkcs8Key) {
|
|
813
|
+
static async getPrivateKeyComponents(pkcs8Key) {
|
|
826
814
|
core.Guards.uint8Array(RSA._CLASS_NAME, "pkcs8Key", pkcs8Key);
|
|
827
815
|
const privateKey = node_crypto.createPrivateKey({
|
|
828
816
|
key: Buffer.from(pkcs8Key),
|
|
@@ -846,7 +834,7 @@ class RSA {
|
|
|
846
834
|
* @param spkiKey The SPKI key as Uint8Array.
|
|
847
835
|
* @returns The key components.
|
|
848
836
|
*/
|
|
849
|
-
static getPublicKeyComponents(spkiKey) {
|
|
837
|
+
static async getPublicKeyComponents(spkiKey) {
|
|
850
838
|
core.Guards.uint8Array(RSA._CLASS_NAME, "spkiKey", spkiKey);
|
|
851
839
|
const publicKey = node_crypto.createPublicKey({
|
|
852
840
|
key: Buffer.from(spkiKey),
|
|
@@ -876,21 +864,22 @@ class RSA {
|
|
|
876
864
|
return BigInt(`0x${hexString}`);
|
|
877
865
|
}
|
|
878
866
|
/**
|
|
879
|
-
* Encrypt the data.
|
|
867
|
+
* Encrypt the data using the public key.
|
|
880
868
|
* @param data The data to encrypt.
|
|
881
869
|
* @returns The data encrypted.
|
|
882
870
|
*/
|
|
883
|
-
|
|
871
|
+
async publicEncrypt(data) {
|
|
884
872
|
core.Guards.uint8Array(RSA._CLASS_NAME, "data", data);
|
|
885
873
|
if (data.length === 0) {
|
|
886
874
|
return new Uint8Array(0);
|
|
887
875
|
}
|
|
876
|
+
const keyDetails = await this.calculateKeyDetails();
|
|
888
877
|
const blocks = [];
|
|
889
878
|
// Split data into blocks of block size
|
|
890
|
-
for (let i = 0; i < data.length; i +=
|
|
891
|
-
const block = data.slice(i, i +
|
|
879
|
+
for (let i = 0; i < data.length; i += keyDetails.blockSize) {
|
|
880
|
+
const block = data.slice(i, i + keyDetails.blockSize);
|
|
892
881
|
const encryptedBlock = node_crypto.publicEncrypt({
|
|
893
|
-
key:
|
|
882
|
+
key: keyDetails.publicKey,
|
|
894
883
|
padding: node_crypto.constants.RSA_PKCS1_OAEP_PADDING
|
|
895
884
|
}, block);
|
|
896
885
|
blocks.push(encryptedBlock);
|
|
@@ -898,14 +887,41 @@ class RSA {
|
|
|
898
887
|
return core.Uint8ArrayHelper.concat(blocks);
|
|
899
888
|
}
|
|
900
889
|
/**
|
|
901
|
-
*
|
|
890
|
+
* Encrypt the data using the private key.
|
|
891
|
+
* @param data The data to encrypt.
|
|
892
|
+
* @returns The data encrypted.
|
|
893
|
+
*/
|
|
894
|
+
async privateEncrypt(data) {
|
|
895
|
+
core.Guards.uint8Array(RSA._CLASS_NAME, "data", data);
|
|
896
|
+
const keyDetails = await this.calculateKeyDetails();
|
|
897
|
+
if (core.Is.empty(keyDetails.privateKey)) {
|
|
898
|
+
throw new core.GeneralError(RSA._CLASS_NAME, "noPrivateKey");
|
|
899
|
+
}
|
|
900
|
+
if (data.length === 0) {
|
|
901
|
+
return new Uint8Array(0);
|
|
902
|
+
}
|
|
903
|
+
const blocks = [];
|
|
904
|
+
// Split data into blocks of block size
|
|
905
|
+
for (let i = 0; i < data.length; i += keyDetails.blockSize) {
|
|
906
|
+
const block = data.slice(i, i + keyDetails.blockSize);
|
|
907
|
+
const encryptedBlock = node_crypto.privateEncrypt({
|
|
908
|
+
key: keyDetails.privateKey,
|
|
909
|
+
padding: node_crypto.constants.RSA_PKCS1_PADDING
|
|
910
|
+
}, block);
|
|
911
|
+
blocks.push(encryptedBlock);
|
|
912
|
+
}
|
|
913
|
+
return core.Uint8ArrayHelper.concat(blocks);
|
|
914
|
+
}
|
|
915
|
+
/**
|
|
916
|
+
* Decrypt the data using the private key.
|
|
902
917
|
* @param data The data to decrypt.
|
|
903
918
|
* @returns The data decrypted.
|
|
904
919
|
* @throws GeneralError If no private key is provided.
|
|
905
920
|
*/
|
|
906
|
-
|
|
921
|
+
async privateDecrypt(data) {
|
|
907
922
|
core.Guards.uint8Array(RSA._CLASS_NAME, "data", data);
|
|
908
|
-
|
|
923
|
+
const keyDetails = await this.calculateKeyDetails();
|
|
924
|
+
if (core.Is.empty(keyDetails.privateKey)) {
|
|
909
925
|
throw new core.GeneralError(RSA._CLASS_NAME, "noPrivateKey");
|
|
910
926
|
}
|
|
911
927
|
if (data.length === 0) {
|
|
@@ -913,16 +929,77 @@ class RSA {
|
|
|
913
929
|
}
|
|
914
930
|
const blocks = [];
|
|
915
931
|
// Split encrypted data into blocks of key size
|
|
916
|
-
for (let i = 0; i < data.length; i +=
|
|
917
|
-
const block = data.slice(i, i +
|
|
932
|
+
for (let i = 0; i < data.length; i += keyDetails.keySize) {
|
|
933
|
+
const block = data.slice(i, i + keyDetails.keySize);
|
|
918
934
|
const decryptedBlock = node_crypto.privateDecrypt({
|
|
919
|
-
key:
|
|
935
|
+
key: keyDetails.privateKey,
|
|
920
936
|
padding: node_crypto.constants.RSA_PKCS1_OAEP_PADDING
|
|
921
937
|
}, block);
|
|
922
938
|
blocks.push(decryptedBlock);
|
|
923
939
|
}
|
|
924
940
|
return core.Uint8ArrayHelper.concat(blocks);
|
|
925
941
|
}
|
|
942
|
+
/**
|
|
943
|
+
* Decrypt the data using the public key.
|
|
944
|
+
* @param data The data to decrypt.
|
|
945
|
+
* @returns The data decrypted.
|
|
946
|
+
*/
|
|
947
|
+
async publicDecrypt(data) {
|
|
948
|
+
core.Guards.uint8Array(RSA._CLASS_NAME, "data", data);
|
|
949
|
+
const keyDetails = await this.calculateKeyDetails();
|
|
950
|
+
if (data.length === 0) {
|
|
951
|
+
return new Uint8Array(0);
|
|
952
|
+
}
|
|
953
|
+
const blocks = [];
|
|
954
|
+
// Split encrypted data into blocks of key size
|
|
955
|
+
for (let i = 0; i < data.length; i += keyDetails.keySize) {
|
|
956
|
+
const block = data.slice(i, i + keyDetails.keySize);
|
|
957
|
+
const decryptedBlock = node_crypto.publicDecrypt({
|
|
958
|
+
key: keyDetails.publicKey,
|
|
959
|
+
padding: node_crypto.constants.RSA_PKCS1_PADDING
|
|
960
|
+
}, block);
|
|
961
|
+
blocks.push(decryptedBlock);
|
|
962
|
+
}
|
|
963
|
+
return core.Uint8ArrayHelper.concat(blocks);
|
|
964
|
+
}
|
|
965
|
+
/**
|
|
966
|
+
* Calculate key details.
|
|
967
|
+
* @internal
|
|
968
|
+
*/
|
|
969
|
+
async calculateKeyDetails() {
|
|
970
|
+
if (core.Is.empty(this._publicKey) || core.Is.empty(this._keySize) || core.Is.empty(this._blockSize)) {
|
|
971
|
+
this._publicKey = node_crypto.createPublicKey({
|
|
972
|
+
key: Buffer.from(this._publicKeyBytes),
|
|
973
|
+
format: "der",
|
|
974
|
+
type: "spki"
|
|
975
|
+
});
|
|
976
|
+
if (!core.Is.empty(this._privateKeyBytes)) {
|
|
977
|
+
this._privateKey = node_crypto.createPrivateKey({
|
|
978
|
+
key: Buffer.from(this._privateKeyBytes),
|
|
979
|
+
format: "der",
|
|
980
|
+
type: "pkcs8"
|
|
981
|
+
});
|
|
982
|
+
}
|
|
983
|
+
// Get modulus length in bits from key details
|
|
984
|
+
const modulusLengthBits = this._publicKey.asymmetricKeyDetails?.modulusLength;
|
|
985
|
+
if (core.Is.empty(modulusLengthBits)) {
|
|
986
|
+
throw new core.GeneralError(RSA._CLASS_NAME, "invalidKeySize");
|
|
987
|
+
}
|
|
988
|
+
// Convert bits to bytes
|
|
989
|
+
this._keySize = Math.ceil(modulusLengthBits / 8);
|
|
990
|
+
// Calculate block size for OAEP with SHA-256
|
|
991
|
+
// Formula: keySize - 2 * hashLength - 2
|
|
992
|
+
const hashLength = 32; // SHA-256 = 32 bytes
|
|
993
|
+
// eslint-disable-next-line no-mixed-operators
|
|
994
|
+
this._blockSize = this._keySize - 2 * hashLength - 2;
|
|
995
|
+
}
|
|
996
|
+
return {
|
|
997
|
+
publicKey: this._publicKey,
|
|
998
|
+
privateKey: this._privateKey,
|
|
999
|
+
keySize: this._keySize,
|
|
1000
|
+
blockSize: this._blockSize
|
|
1001
|
+
};
|
|
1002
|
+
}
|
|
926
1003
|
}
|
|
927
1004
|
|
|
928
1005
|
// Copyright 2024 IOTA Stiftung.
|
package/dist/esm/index.mjs
CHANGED
|
@@ -6,7 +6,7 @@ import { blake2b } from '@noble/hashes/blake2b';
|
|
|
6
6
|
import { HDKey as HDKey$1 } from '@scure/bip32';
|
|
7
7
|
import { HDKey } from 'micro-key-producer/slip10.js';
|
|
8
8
|
import { chacha20poly1305 } from '@noble/ciphers/chacha';
|
|
9
|
-
import {
|
|
9
|
+
import { generateKeyPairSync, createPrivateKey, createPublicKey, publicEncrypt, constants, privateEncrypt, privateDecrypt, publicDecrypt } from 'node:crypto';
|
|
10
10
|
import { blake3 } from '@noble/hashes/blake3';
|
|
11
11
|
import { hmac } from '@noble/hashes/hmac';
|
|
12
12
|
import { sha1 } from '@noble/hashes/sha1';
|
|
@@ -704,6 +704,16 @@ class RSA {
|
|
|
704
704
|
* @internal
|
|
705
705
|
*/
|
|
706
706
|
static _CLASS_NAME = "RSA";
|
|
707
|
+
/**
|
|
708
|
+
* The public key for encryption.
|
|
709
|
+
* @internal
|
|
710
|
+
*/
|
|
711
|
+
_publicKeyBytes;
|
|
712
|
+
/**
|
|
713
|
+
* The private key for decryption.
|
|
714
|
+
* @internal
|
|
715
|
+
*/
|
|
716
|
+
_privateKeyBytes;
|
|
707
717
|
/**
|
|
708
718
|
* The public key for encryption.
|
|
709
719
|
* @internal
|
|
@@ -731,37 +741,15 @@ class RSA {
|
|
|
731
741
|
*/
|
|
732
742
|
constructor(publicKey, privateKey) {
|
|
733
743
|
Guards.uint8Array(RSA._CLASS_NAME, "publicKey", publicKey);
|
|
734
|
-
this.
|
|
735
|
-
|
|
736
|
-
format: "der",
|
|
737
|
-
type: "spki"
|
|
738
|
-
});
|
|
739
|
-
if (!Is.empty(privateKey)) {
|
|
740
|
-
this._privateKey = createPrivateKey({
|
|
741
|
-
key: Buffer.from(privateKey),
|
|
742
|
-
format: "der",
|
|
743
|
-
type: "pkcs8"
|
|
744
|
-
});
|
|
745
|
-
}
|
|
746
|
-
// Get modulus length in bits from key details
|
|
747
|
-
const modulusLengthBits = this._publicKey.asymmetricKeyDetails?.modulusLength;
|
|
748
|
-
if (Is.empty(modulusLengthBits)) {
|
|
749
|
-
throw new GeneralError(RSA._CLASS_NAME, "invalidKeySize");
|
|
750
|
-
}
|
|
751
|
-
// Convert bits to bytes
|
|
752
|
-
this._keySize = Math.ceil(modulusLengthBits / 8);
|
|
753
|
-
// Calculate block size for OAEP with SHA-256
|
|
754
|
-
// Formula: keySize - 2 * hashLength - 2
|
|
755
|
-
const hashLength = 32; // SHA-256 = 32 bytes
|
|
756
|
-
// eslint-disable-next-line no-mixed-operators
|
|
757
|
-
this._blockSize = this._keySize - 2 * hashLength - 2;
|
|
744
|
+
this._publicKeyBytes = publicKey;
|
|
745
|
+
this._privateKeyBytes = privateKey;
|
|
758
746
|
}
|
|
759
747
|
/**
|
|
760
748
|
* Generate a new RSA key pair in PKCS8 format.
|
|
761
749
|
* @param modulusLength The key size in bits (default: 2048).
|
|
762
750
|
* @returns The public and private keys as Uint8Array.
|
|
763
751
|
*/
|
|
764
|
-
static generateKeyPair(modulusLength = 2048) {
|
|
752
|
+
static async generateKeyPair(modulusLength = 2048) {
|
|
765
753
|
const { publicKey, privateKey } = generateKeyPairSync("rsa", {
|
|
766
754
|
modulusLength,
|
|
767
755
|
publicKeyEncoding: {
|
|
@@ -783,7 +771,7 @@ class RSA {
|
|
|
783
771
|
* @param pkcs1Key The PKCS1 key as Uint8Array.
|
|
784
772
|
* @returns The PKCS8 key as Uint8Array.
|
|
785
773
|
*/
|
|
786
|
-
static convertPkcs1ToPkcs8(pkcs1Key) {
|
|
774
|
+
static async convertPkcs1ToPkcs8(pkcs1Key) {
|
|
787
775
|
Guards.uint8Array(RSA._CLASS_NAME, "pkcs1Key", pkcs1Key);
|
|
788
776
|
const privateKey = createPrivateKey({
|
|
789
777
|
key: Buffer.from(pkcs1Key),
|
|
@@ -800,7 +788,7 @@ class RSA {
|
|
|
800
788
|
* @param pkcs8Key The PKCS8 key as Uint8Array.
|
|
801
789
|
* @returns The key components.
|
|
802
790
|
*/
|
|
803
|
-
static getPrivateKeyComponents(pkcs8Key) {
|
|
791
|
+
static async getPrivateKeyComponents(pkcs8Key) {
|
|
804
792
|
Guards.uint8Array(RSA._CLASS_NAME, "pkcs8Key", pkcs8Key);
|
|
805
793
|
const privateKey = createPrivateKey({
|
|
806
794
|
key: Buffer.from(pkcs8Key),
|
|
@@ -824,7 +812,7 @@ class RSA {
|
|
|
824
812
|
* @param spkiKey The SPKI key as Uint8Array.
|
|
825
813
|
* @returns The key components.
|
|
826
814
|
*/
|
|
827
|
-
static getPublicKeyComponents(spkiKey) {
|
|
815
|
+
static async getPublicKeyComponents(spkiKey) {
|
|
828
816
|
Guards.uint8Array(RSA._CLASS_NAME, "spkiKey", spkiKey);
|
|
829
817
|
const publicKey = createPublicKey({
|
|
830
818
|
key: Buffer.from(spkiKey),
|
|
@@ -854,21 +842,22 @@ class RSA {
|
|
|
854
842
|
return BigInt(`0x${hexString}`);
|
|
855
843
|
}
|
|
856
844
|
/**
|
|
857
|
-
* Encrypt the data.
|
|
845
|
+
* Encrypt the data using the public key.
|
|
858
846
|
* @param data The data to encrypt.
|
|
859
847
|
* @returns The data encrypted.
|
|
860
848
|
*/
|
|
861
|
-
|
|
849
|
+
async publicEncrypt(data) {
|
|
862
850
|
Guards.uint8Array(RSA._CLASS_NAME, "data", data);
|
|
863
851
|
if (data.length === 0) {
|
|
864
852
|
return new Uint8Array(0);
|
|
865
853
|
}
|
|
854
|
+
const keyDetails = await this.calculateKeyDetails();
|
|
866
855
|
const blocks = [];
|
|
867
856
|
// Split data into blocks of block size
|
|
868
|
-
for (let i = 0; i < data.length; i +=
|
|
869
|
-
const block = data.slice(i, i +
|
|
857
|
+
for (let i = 0; i < data.length; i += keyDetails.blockSize) {
|
|
858
|
+
const block = data.slice(i, i + keyDetails.blockSize);
|
|
870
859
|
const encryptedBlock = publicEncrypt({
|
|
871
|
-
key:
|
|
860
|
+
key: keyDetails.publicKey,
|
|
872
861
|
padding: constants.RSA_PKCS1_OAEP_PADDING
|
|
873
862
|
}, block);
|
|
874
863
|
blocks.push(encryptedBlock);
|
|
@@ -876,14 +865,41 @@ class RSA {
|
|
|
876
865
|
return Uint8ArrayHelper.concat(blocks);
|
|
877
866
|
}
|
|
878
867
|
/**
|
|
879
|
-
*
|
|
868
|
+
* Encrypt the data using the private key.
|
|
869
|
+
* @param data The data to encrypt.
|
|
870
|
+
* @returns The data encrypted.
|
|
871
|
+
*/
|
|
872
|
+
async privateEncrypt(data) {
|
|
873
|
+
Guards.uint8Array(RSA._CLASS_NAME, "data", data);
|
|
874
|
+
const keyDetails = await this.calculateKeyDetails();
|
|
875
|
+
if (Is.empty(keyDetails.privateKey)) {
|
|
876
|
+
throw new GeneralError(RSA._CLASS_NAME, "noPrivateKey");
|
|
877
|
+
}
|
|
878
|
+
if (data.length === 0) {
|
|
879
|
+
return new Uint8Array(0);
|
|
880
|
+
}
|
|
881
|
+
const blocks = [];
|
|
882
|
+
// Split data into blocks of block size
|
|
883
|
+
for (let i = 0; i < data.length; i += keyDetails.blockSize) {
|
|
884
|
+
const block = data.slice(i, i + keyDetails.blockSize);
|
|
885
|
+
const encryptedBlock = privateEncrypt({
|
|
886
|
+
key: keyDetails.privateKey,
|
|
887
|
+
padding: constants.RSA_PKCS1_PADDING
|
|
888
|
+
}, block);
|
|
889
|
+
blocks.push(encryptedBlock);
|
|
890
|
+
}
|
|
891
|
+
return Uint8ArrayHelper.concat(blocks);
|
|
892
|
+
}
|
|
893
|
+
/**
|
|
894
|
+
* Decrypt the data using the private key.
|
|
880
895
|
* @param data The data to decrypt.
|
|
881
896
|
* @returns The data decrypted.
|
|
882
897
|
* @throws GeneralError If no private key is provided.
|
|
883
898
|
*/
|
|
884
|
-
|
|
899
|
+
async privateDecrypt(data) {
|
|
885
900
|
Guards.uint8Array(RSA._CLASS_NAME, "data", data);
|
|
886
|
-
|
|
901
|
+
const keyDetails = await this.calculateKeyDetails();
|
|
902
|
+
if (Is.empty(keyDetails.privateKey)) {
|
|
887
903
|
throw new GeneralError(RSA._CLASS_NAME, "noPrivateKey");
|
|
888
904
|
}
|
|
889
905
|
if (data.length === 0) {
|
|
@@ -891,16 +907,77 @@ class RSA {
|
|
|
891
907
|
}
|
|
892
908
|
const blocks = [];
|
|
893
909
|
// Split encrypted data into blocks of key size
|
|
894
|
-
for (let i = 0; i < data.length; i +=
|
|
895
|
-
const block = data.slice(i, i +
|
|
910
|
+
for (let i = 0; i < data.length; i += keyDetails.keySize) {
|
|
911
|
+
const block = data.slice(i, i + keyDetails.keySize);
|
|
896
912
|
const decryptedBlock = privateDecrypt({
|
|
897
|
-
key:
|
|
913
|
+
key: keyDetails.privateKey,
|
|
898
914
|
padding: constants.RSA_PKCS1_OAEP_PADDING
|
|
899
915
|
}, block);
|
|
900
916
|
blocks.push(decryptedBlock);
|
|
901
917
|
}
|
|
902
918
|
return Uint8ArrayHelper.concat(blocks);
|
|
903
919
|
}
|
|
920
|
+
/**
|
|
921
|
+
* Decrypt the data using the public key.
|
|
922
|
+
* @param data The data to decrypt.
|
|
923
|
+
* @returns The data decrypted.
|
|
924
|
+
*/
|
|
925
|
+
async publicDecrypt(data) {
|
|
926
|
+
Guards.uint8Array(RSA._CLASS_NAME, "data", data);
|
|
927
|
+
const keyDetails = await this.calculateKeyDetails();
|
|
928
|
+
if (data.length === 0) {
|
|
929
|
+
return new Uint8Array(0);
|
|
930
|
+
}
|
|
931
|
+
const blocks = [];
|
|
932
|
+
// Split encrypted data into blocks of key size
|
|
933
|
+
for (let i = 0; i < data.length; i += keyDetails.keySize) {
|
|
934
|
+
const block = data.slice(i, i + keyDetails.keySize);
|
|
935
|
+
const decryptedBlock = publicDecrypt({
|
|
936
|
+
key: keyDetails.publicKey,
|
|
937
|
+
padding: constants.RSA_PKCS1_PADDING
|
|
938
|
+
}, block);
|
|
939
|
+
blocks.push(decryptedBlock);
|
|
940
|
+
}
|
|
941
|
+
return Uint8ArrayHelper.concat(blocks);
|
|
942
|
+
}
|
|
943
|
+
/**
|
|
944
|
+
* Calculate key details.
|
|
945
|
+
* @internal
|
|
946
|
+
*/
|
|
947
|
+
async calculateKeyDetails() {
|
|
948
|
+
if (Is.empty(this._publicKey) || Is.empty(this._keySize) || Is.empty(this._blockSize)) {
|
|
949
|
+
this._publicKey = createPublicKey({
|
|
950
|
+
key: Buffer.from(this._publicKeyBytes),
|
|
951
|
+
format: "der",
|
|
952
|
+
type: "spki"
|
|
953
|
+
});
|
|
954
|
+
if (!Is.empty(this._privateKeyBytes)) {
|
|
955
|
+
this._privateKey = createPrivateKey({
|
|
956
|
+
key: Buffer.from(this._privateKeyBytes),
|
|
957
|
+
format: "der",
|
|
958
|
+
type: "pkcs8"
|
|
959
|
+
});
|
|
960
|
+
}
|
|
961
|
+
// Get modulus length in bits from key details
|
|
962
|
+
const modulusLengthBits = this._publicKey.asymmetricKeyDetails?.modulusLength;
|
|
963
|
+
if (Is.empty(modulusLengthBits)) {
|
|
964
|
+
throw new GeneralError(RSA._CLASS_NAME, "invalidKeySize");
|
|
965
|
+
}
|
|
966
|
+
// Convert bits to bytes
|
|
967
|
+
this._keySize = Math.ceil(modulusLengthBits / 8);
|
|
968
|
+
// Calculate block size for OAEP with SHA-256
|
|
969
|
+
// Formula: keySize - 2 * hashLength - 2
|
|
970
|
+
const hashLength = 32; // SHA-256 = 32 bytes
|
|
971
|
+
// eslint-disable-next-line no-mixed-operators
|
|
972
|
+
this._blockSize = this._keySize - 2 * hashLength - 2;
|
|
973
|
+
}
|
|
974
|
+
return {
|
|
975
|
+
publicKey: this._publicKey,
|
|
976
|
+
privateKey: this._privateKey,
|
|
977
|
+
keySize: this._keySize,
|
|
978
|
+
blockSize: this._blockSize
|
|
979
|
+
};
|
|
980
|
+
}
|
|
904
981
|
}
|
|
905
982
|
|
|
906
983
|
// Copyright 2024 IOTA Stiftung.
|
|
@@ -13,22 +13,22 @@ export declare class RSA {
|
|
|
13
13
|
* @param modulusLength The key size in bits (default: 2048).
|
|
14
14
|
* @returns The public and private keys as Uint8Array.
|
|
15
15
|
*/
|
|
16
|
-
static generateKeyPair(modulusLength?: number): {
|
|
16
|
+
static generateKeyPair(modulusLength?: number): Promise<{
|
|
17
17
|
publicKey: Uint8Array;
|
|
18
18
|
privateKey: Uint8Array;
|
|
19
|
-
}
|
|
19
|
+
}>;
|
|
20
20
|
/**
|
|
21
21
|
* Convert a PKCS1 key to a PKCS8 key.
|
|
22
22
|
* @param pkcs1Key The PKCS1 key as Uint8Array.
|
|
23
23
|
* @returns The PKCS8 key as Uint8Array.
|
|
24
24
|
*/
|
|
25
|
-
static convertPkcs1ToPkcs8(pkcs1Key: Uint8Array): Uint8Array
|
|
25
|
+
static convertPkcs1ToPkcs8(pkcs1Key: Uint8Array): Promise<Uint8Array>;
|
|
26
26
|
/**
|
|
27
27
|
* Break the private key down in to its components.
|
|
28
28
|
* @param pkcs8Key The PKCS8 key as Uint8Array.
|
|
29
29
|
* @returns The key components.
|
|
30
30
|
*/
|
|
31
|
-
static getPrivateKeyComponents(pkcs8Key: Uint8Array): {
|
|
31
|
+
static getPrivateKeyComponents(pkcs8Key: Uint8Array): Promise<{
|
|
32
32
|
n: bigint;
|
|
33
33
|
e: bigint;
|
|
34
34
|
d: bigint;
|
|
@@ -37,27 +37,39 @@ export declare class RSA {
|
|
|
37
37
|
dp: bigint;
|
|
38
38
|
dq: bigint;
|
|
39
39
|
qi: bigint;
|
|
40
|
-
}
|
|
40
|
+
}>;
|
|
41
41
|
/**
|
|
42
42
|
* Break the public key down in to its components.
|
|
43
43
|
* @param spkiKey The SPKI key as Uint8Array.
|
|
44
44
|
* @returns The key components.
|
|
45
45
|
*/
|
|
46
|
-
static getPublicKeyComponents(spkiKey: Uint8Array): {
|
|
46
|
+
static getPublicKeyComponents(spkiKey: Uint8Array): Promise<{
|
|
47
47
|
n: bigint;
|
|
48
48
|
e: bigint;
|
|
49
|
-
}
|
|
49
|
+
}>;
|
|
50
50
|
/**
|
|
51
|
-
* Encrypt the data.
|
|
51
|
+
* Encrypt the data using the public key.
|
|
52
52
|
* @param data The data to encrypt.
|
|
53
53
|
* @returns The data encrypted.
|
|
54
54
|
*/
|
|
55
|
-
|
|
55
|
+
publicEncrypt(data: Uint8Array): Promise<Uint8Array>;
|
|
56
56
|
/**
|
|
57
|
-
*
|
|
57
|
+
* Encrypt the data using the private key.
|
|
58
|
+
* @param data The data to encrypt.
|
|
59
|
+
* @returns The data encrypted.
|
|
60
|
+
*/
|
|
61
|
+
privateEncrypt(data: Uint8Array): Promise<Uint8Array>;
|
|
62
|
+
/**
|
|
63
|
+
* Decrypt the data using the private key.
|
|
58
64
|
* @param data The data to decrypt.
|
|
59
65
|
* @returns The data decrypted.
|
|
60
66
|
* @throws GeneralError If no private key is provided.
|
|
61
67
|
*/
|
|
62
|
-
|
|
68
|
+
privateDecrypt(data: Uint8Array): Promise<Uint8Array>;
|
|
69
|
+
/**
|
|
70
|
+
* Decrypt the data using the public key.
|
|
71
|
+
* @param data The data to decrypt.
|
|
72
|
+
* @returns The data decrypted.
|
|
73
|
+
*/
|
|
74
|
+
publicDecrypt(data: Uint8Array): Promise<Uint8Array>;
|
|
63
75
|
}
|
package/docs/changelog.md
CHANGED
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
# @twin.org/crypto - Changelog
|
|
2
2
|
|
|
3
|
+
## [0.0.2-next.4](https://github.com/twinfoundation/framework/compare/crypto-v0.0.2-next.3...crypto-v0.0.2-next.4) (2025-08-15)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* additional RSA methods and async ([1fceee2](https://github.com/twinfoundation/framework/commit/1fceee2d1248a24a7620846025fcf906495c07f4))
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Dependencies
|
|
12
|
+
|
|
13
|
+
* The following workspace dependencies were updated
|
|
14
|
+
* dependencies
|
|
15
|
+
* @twin.org/core bumped from 0.0.2-next.3 to 0.0.2-next.4
|
|
16
|
+
* @twin.org/nameof bumped from 0.0.2-next.3 to 0.0.2-next.4
|
|
17
|
+
* devDependencies
|
|
18
|
+
* @twin.org/nameof-transformer bumped from 0.0.2-next.3 to 0.0.2-next.4
|
|
19
|
+
* @twin.org/nameof-vitest-plugin bumped from 0.0.2-next.3 to 0.0.2-next.4
|
|
20
|
+
|
|
3
21
|
## [0.0.2-next.3](https://github.com/twinfoundation/framework/compare/crypto-v0.0.2-next.2...crypto-v0.0.2-next.3) (2025-08-06)
|
|
4
22
|
|
|
5
23
|
|
|
@@ -32,7 +32,7 @@ The private key for decryption (DER format as Uint8Array).
|
|
|
32
32
|
|
|
33
33
|
### generateKeyPair()
|
|
34
34
|
|
|
35
|
-
> `static` **generateKeyPair**(`modulusLength`): `
|
|
35
|
+
> `static` **generateKeyPair**(`modulusLength`): `Promise`\<\{ `publicKey`: `Uint8Array`; `privateKey`: `Uint8Array`; \}\>
|
|
36
36
|
|
|
37
37
|
Generate a new RSA key pair in PKCS8 format.
|
|
38
38
|
|
|
@@ -46,23 +46,15 @@ The key size in bits (default: 2048).
|
|
|
46
46
|
|
|
47
47
|
#### Returns
|
|
48
48
|
|
|
49
|
-
`
|
|
49
|
+
`Promise`\<\{ `publicKey`: `Uint8Array`; `privateKey`: `Uint8Array`; \}\>
|
|
50
50
|
|
|
51
51
|
The public and private keys as Uint8Array.
|
|
52
52
|
|
|
53
|
-
##### publicKey
|
|
54
|
-
|
|
55
|
-
> **publicKey**: `Uint8Array`
|
|
56
|
-
|
|
57
|
-
##### privateKey
|
|
58
|
-
|
|
59
|
-
> **privateKey**: `Uint8Array`
|
|
60
|
-
|
|
61
53
|
***
|
|
62
54
|
|
|
63
55
|
### convertPkcs1ToPkcs8()
|
|
64
56
|
|
|
65
|
-
> `static` **convertPkcs1ToPkcs8**(`pkcs1Key`): `Uint8Array
|
|
57
|
+
> `static` **convertPkcs1ToPkcs8**(`pkcs1Key`): `Promise`\<`Uint8Array`\<`ArrayBufferLike`\>\>
|
|
66
58
|
|
|
67
59
|
Convert a PKCS1 key to a PKCS8 key.
|
|
68
60
|
|
|
@@ -76,7 +68,7 @@ The PKCS1 key as Uint8Array.
|
|
|
76
68
|
|
|
77
69
|
#### Returns
|
|
78
70
|
|
|
79
|
-
`Uint8Array
|
|
71
|
+
`Promise`\<`Uint8Array`\<`ArrayBufferLike`\>\>
|
|
80
72
|
|
|
81
73
|
The PKCS8 key as Uint8Array.
|
|
82
74
|
|
|
@@ -84,7 +76,7 @@ The PKCS8 key as Uint8Array.
|
|
|
84
76
|
|
|
85
77
|
### getPrivateKeyComponents()
|
|
86
78
|
|
|
87
|
-
> `static` **getPrivateKeyComponents**(`pkcs8Key`): `
|
|
79
|
+
> `static` **getPrivateKeyComponents**(`pkcs8Key`): `Promise`\<\{ `n`: `bigint`; `e`: `bigint`; `d`: `bigint`; `p`: `bigint`; `q`: `bigint`; `dp`: `bigint`; `dq`: `bigint`; `qi`: `bigint`; \}\>
|
|
88
80
|
|
|
89
81
|
Break the private key down in to its components.
|
|
90
82
|
|
|
@@ -98,79 +90,61 @@ The PKCS8 key as Uint8Array.
|
|
|
98
90
|
|
|
99
91
|
#### Returns
|
|
100
92
|
|
|
101
|
-
`
|
|
93
|
+
`Promise`\<\{ `n`: `bigint`; `e`: `bigint`; `d`: `bigint`; `p`: `bigint`; `q`: `bigint`; `dp`: `bigint`; `dq`: `bigint`; `qi`: `bigint`; \}\>
|
|
102
94
|
|
|
103
95
|
The key components.
|
|
104
96
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
> **n**: `bigint`
|
|
108
|
-
|
|
109
|
-
##### e
|
|
110
|
-
|
|
111
|
-
> **e**: `bigint`
|
|
112
|
-
|
|
113
|
-
##### d
|
|
114
|
-
|
|
115
|
-
> **d**: `bigint`
|
|
97
|
+
***
|
|
116
98
|
|
|
117
|
-
|
|
99
|
+
### getPublicKeyComponents()
|
|
118
100
|
|
|
119
|
-
> **
|
|
101
|
+
> `static` **getPublicKeyComponents**(`spkiKey`): `Promise`\<\{ `n`: `bigint`; `e`: `bigint`; \}\>
|
|
120
102
|
|
|
121
|
-
|
|
103
|
+
Break the public key down in to its components.
|
|
122
104
|
|
|
123
|
-
|
|
105
|
+
#### Parameters
|
|
124
106
|
|
|
125
|
-
#####
|
|
107
|
+
##### spkiKey
|
|
126
108
|
|
|
127
|
-
|
|
109
|
+
`Uint8Array`
|
|
128
110
|
|
|
129
|
-
|
|
111
|
+
The SPKI key as Uint8Array.
|
|
130
112
|
|
|
131
|
-
|
|
113
|
+
#### Returns
|
|
132
114
|
|
|
133
|
-
|
|
115
|
+
`Promise`\<\{ `n`: `bigint`; `e`: `bigint`; \}\>
|
|
134
116
|
|
|
135
|
-
|
|
117
|
+
The key components.
|
|
136
118
|
|
|
137
119
|
***
|
|
138
120
|
|
|
139
|
-
###
|
|
121
|
+
### publicEncrypt()
|
|
140
122
|
|
|
141
|
-
>
|
|
123
|
+
> **publicEncrypt**(`data`): `Promise`\<`Uint8Array`\<`ArrayBufferLike`\>\>
|
|
142
124
|
|
|
143
|
-
|
|
125
|
+
Encrypt the data using the public key.
|
|
144
126
|
|
|
145
127
|
#### Parameters
|
|
146
128
|
|
|
147
|
-
#####
|
|
129
|
+
##### data
|
|
148
130
|
|
|
149
131
|
`Uint8Array`
|
|
150
132
|
|
|
151
|
-
The
|
|
133
|
+
The data to encrypt.
|
|
152
134
|
|
|
153
135
|
#### Returns
|
|
154
136
|
|
|
155
|
-
`
|
|
137
|
+
`Promise`\<`Uint8Array`\<`ArrayBufferLike`\>\>
|
|
156
138
|
|
|
157
|
-
The
|
|
158
|
-
|
|
159
|
-
##### n
|
|
160
|
-
|
|
161
|
-
> **n**: `bigint`
|
|
162
|
-
|
|
163
|
-
##### e
|
|
164
|
-
|
|
165
|
-
> **e**: `bigint`
|
|
139
|
+
The data encrypted.
|
|
166
140
|
|
|
167
141
|
***
|
|
168
142
|
|
|
169
|
-
###
|
|
143
|
+
### privateEncrypt()
|
|
170
144
|
|
|
171
|
-
> **
|
|
145
|
+
> **privateEncrypt**(`data`): `Promise`\<`Uint8Array`\<`ArrayBufferLike`\>\>
|
|
172
146
|
|
|
173
|
-
Encrypt the data.
|
|
147
|
+
Encrypt the data using the private key.
|
|
174
148
|
|
|
175
149
|
#### Parameters
|
|
176
150
|
|
|
@@ -182,17 +156,17 @@ The data to encrypt.
|
|
|
182
156
|
|
|
183
157
|
#### Returns
|
|
184
158
|
|
|
185
|
-
`Uint8Array
|
|
159
|
+
`Promise`\<`Uint8Array`\<`ArrayBufferLike`\>\>
|
|
186
160
|
|
|
187
161
|
The data encrypted.
|
|
188
162
|
|
|
189
163
|
***
|
|
190
164
|
|
|
191
|
-
###
|
|
165
|
+
### privateDecrypt()
|
|
192
166
|
|
|
193
|
-
> **
|
|
167
|
+
> **privateDecrypt**(`data`): `Promise`\<`Uint8Array`\<`ArrayBufferLike`\>\>
|
|
194
168
|
|
|
195
|
-
Decrypt the data.
|
|
169
|
+
Decrypt the data using the private key.
|
|
196
170
|
|
|
197
171
|
#### Parameters
|
|
198
172
|
|
|
@@ -204,10 +178,32 @@ The data to decrypt.
|
|
|
204
178
|
|
|
205
179
|
#### Returns
|
|
206
180
|
|
|
207
|
-
`Uint8Array
|
|
181
|
+
`Promise`\<`Uint8Array`\<`ArrayBufferLike`\>\>
|
|
208
182
|
|
|
209
183
|
The data decrypted.
|
|
210
184
|
|
|
211
185
|
#### Throws
|
|
212
186
|
|
|
213
187
|
GeneralError If no private key is provided.
|
|
188
|
+
|
|
189
|
+
***
|
|
190
|
+
|
|
191
|
+
### publicDecrypt()
|
|
192
|
+
|
|
193
|
+
> **publicDecrypt**(`data`): `Promise`\<`Uint8Array`\<`ArrayBufferLike`\>\>
|
|
194
|
+
|
|
195
|
+
Decrypt the data using the public key.
|
|
196
|
+
|
|
197
|
+
#### Parameters
|
|
198
|
+
|
|
199
|
+
##### data
|
|
200
|
+
|
|
201
|
+
`Uint8Array`
|
|
202
|
+
|
|
203
|
+
The data to decrypt.
|
|
204
|
+
|
|
205
|
+
#### Returns
|
|
206
|
+
|
|
207
|
+
`Promise`\<`Uint8Array`\<`ArrayBufferLike`\>\>
|
|
208
|
+
|
|
209
|
+
The data decrypted.
|
package/locales/en.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@twin.org/crypto",
|
|
3
|
-
"version": "0.0.2-next.
|
|
3
|
+
"version": "0.0.2-next.4",
|
|
4
4
|
"description": "Contains helper methods and classes which implement cryptographic functions",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -20,8 +20,9 @@
|
|
|
20
20
|
"@scure/base": "1.2.6",
|
|
21
21
|
"@scure/bip32": "1.7.0",
|
|
22
22
|
"@scure/bip39": "1.6.0",
|
|
23
|
-
"@twin.org/core": "0.0.2-next.
|
|
24
|
-
"@twin.org/nameof": "0.0.2-next.
|
|
23
|
+
"@twin.org/core": "0.0.2-next.4",
|
|
24
|
+
"@twin.org/nameof": "0.0.2-next.4",
|
|
25
|
+
"crypto-browserify": "3.12.1",
|
|
25
26
|
"micro-key-producer": "0.7.6"
|
|
26
27
|
},
|
|
27
28
|
"main": "./dist/cjs/index.cjs",
|