@ursalock/client 0.4.0 → 0.4.1
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/index.js +1 -129
- package/package.json +2 -1
package/dist/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { ZKCredentials } from '@z-base/zero-knowledge-credentials';
|
|
2
2
|
import { useCallback, useSyncExternalStore } from 'react';
|
|
3
|
+
import { encrypt, computeHmac, verifyHmac, decrypt } from '@ursalock/crypto';
|
|
3
4
|
|
|
4
5
|
// src/passkey.ts
|
|
5
6
|
|
|
@@ -801,135 +802,6 @@ function useCredential(client) {
|
|
|
801
802
|
function usePasskeySupport(client) {
|
|
802
803
|
return client.supportsPasskey();
|
|
803
804
|
}
|
|
804
|
-
|
|
805
|
-
// ../crypto/dist/index.js
|
|
806
|
-
function randomBytes(length) {
|
|
807
|
-
const bytes = new Uint8Array(length);
|
|
808
|
-
crypto.getRandomValues(bytes);
|
|
809
|
-
return bytes;
|
|
810
|
-
}
|
|
811
|
-
function concatBytes(...arrays) {
|
|
812
|
-
const totalLength = arrays.reduce((sum, arr) => sum + arr.length, 0);
|
|
813
|
-
const result = new Uint8Array(totalLength);
|
|
814
|
-
let offset = 0;
|
|
815
|
-
for (const arr of arrays) {
|
|
816
|
-
result.set(arr, offset);
|
|
817
|
-
offset += arr.length;
|
|
818
|
-
}
|
|
819
|
-
return result;
|
|
820
|
-
}
|
|
821
|
-
var IV_LENGTH = 12;
|
|
822
|
-
var WebCryptoProvider = class {
|
|
823
|
-
async encrypt(plaintext, key) {
|
|
824
|
-
if (key.length !== 32) {
|
|
825
|
-
throw new Error(`Invalid key length: expected 32 bytes, got ${key.length}`);
|
|
826
|
-
}
|
|
827
|
-
const actualIv = randomBytes(IV_LENGTH);
|
|
828
|
-
const cryptoKey = await crypto.subtle.importKey(
|
|
829
|
-
"raw",
|
|
830
|
-
key.buffer.slice(key.byteOffset, key.byteOffset + key.byteLength),
|
|
831
|
-
{ name: "AES-GCM" },
|
|
832
|
-
false,
|
|
833
|
-
["encrypt"]
|
|
834
|
-
);
|
|
835
|
-
const ciphertext = new Uint8Array(
|
|
836
|
-
await crypto.subtle.encrypt(
|
|
837
|
-
{ name: "AES-GCM", iv: actualIv },
|
|
838
|
-
cryptoKey,
|
|
839
|
-
plaintext.buffer.slice(plaintext.byteOffset, plaintext.byteOffset + plaintext.byteLength)
|
|
840
|
-
)
|
|
841
|
-
);
|
|
842
|
-
const combined = concatBytes(actualIv, ciphertext);
|
|
843
|
-
return { iv: actualIv, ciphertext, combined };
|
|
844
|
-
}
|
|
845
|
-
async decrypt(encrypted, key) {
|
|
846
|
-
if (key.length !== 32) {
|
|
847
|
-
throw new Error(`Invalid key length: expected 32 bytes, got ${key.length}`);
|
|
848
|
-
}
|
|
849
|
-
let iv;
|
|
850
|
-
let ciphertext;
|
|
851
|
-
if (encrypted instanceof Uint8Array) {
|
|
852
|
-
if (encrypted.length < IV_LENGTH + 16) {
|
|
853
|
-
throw new Error("Invalid encrypted data: too short");
|
|
854
|
-
}
|
|
855
|
-
iv = encrypted.slice(0, IV_LENGTH);
|
|
856
|
-
ciphertext = encrypted.slice(IV_LENGTH);
|
|
857
|
-
} else {
|
|
858
|
-
iv = encrypted.iv;
|
|
859
|
-
ciphertext = encrypted.ciphertext;
|
|
860
|
-
}
|
|
861
|
-
const cryptoKey = await crypto.subtle.importKey(
|
|
862
|
-
"raw",
|
|
863
|
-
key.buffer.slice(key.byteOffset, key.byteOffset + key.byteLength),
|
|
864
|
-
{ name: "AES-GCM" },
|
|
865
|
-
false,
|
|
866
|
-
["decrypt"]
|
|
867
|
-
);
|
|
868
|
-
try {
|
|
869
|
-
const plaintext = await crypto.subtle.decrypt(
|
|
870
|
-
{ name: "AES-GCM", iv },
|
|
871
|
-
cryptoKey,
|
|
872
|
-
ciphertext.buffer.slice(ciphertext.byteOffset, ciphertext.byteOffset + ciphertext.byteLength)
|
|
873
|
-
);
|
|
874
|
-
return new Uint8Array(plaintext);
|
|
875
|
-
} catch (error) {
|
|
876
|
-
throw new Error("Decryption failed: invalid key or corrupted data");
|
|
877
|
-
}
|
|
878
|
-
}
|
|
879
|
-
};
|
|
880
|
-
var defaultProvider = new WebCryptoProvider();
|
|
881
|
-
async function encrypt(plaintext, key, provider = defaultProvider) {
|
|
882
|
-
return provider.encrypt(plaintext, key);
|
|
883
|
-
}
|
|
884
|
-
async function decrypt(encrypted, key, provider = defaultProvider) {
|
|
885
|
-
return provider.decrypt(encrypted, key);
|
|
886
|
-
}
|
|
887
|
-
async function computeHmac(data, key) {
|
|
888
|
-
const cryptoKey = await crypto.subtle.importKey(
|
|
889
|
-
"raw",
|
|
890
|
-
key,
|
|
891
|
-
{ name: "HMAC", hash: "SHA-256" },
|
|
892
|
-
false,
|
|
893
|
-
["sign"]
|
|
894
|
-
);
|
|
895
|
-
const signature = new Uint8Array(
|
|
896
|
-
await crypto.subtle.sign("HMAC", cryptoKey, data)
|
|
897
|
-
);
|
|
898
|
-
return bytesToHex(signature);
|
|
899
|
-
}
|
|
900
|
-
async function verifyHmac(data, key, expectedHmac) {
|
|
901
|
-
const cryptoKey = await crypto.subtle.importKey(
|
|
902
|
-
"raw",
|
|
903
|
-
key,
|
|
904
|
-
{ name: "HMAC", hash: "SHA-256" },
|
|
905
|
-
false,
|
|
906
|
-
["verify"]
|
|
907
|
-
);
|
|
908
|
-
const expectedBytes = hexToBytes(expectedHmac);
|
|
909
|
-
return crypto.subtle.verify(
|
|
910
|
-
"HMAC",
|
|
911
|
-
cryptoKey,
|
|
912
|
-
expectedBytes,
|
|
913
|
-
data
|
|
914
|
-
);
|
|
915
|
-
}
|
|
916
|
-
function bytesToHex(bytes) {
|
|
917
|
-
let hex = "";
|
|
918
|
-
for (let i = 0; i < bytes.length; i++) {
|
|
919
|
-
hex += bytes[i].toString(16).padStart(2, "0");
|
|
920
|
-
}
|
|
921
|
-
return hex;
|
|
922
|
-
}
|
|
923
|
-
function hexToBytes(hex) {
|
|
924
|
-
const len = hex.length >>> 1;
|
|
925
|
-
const bytes = new Uint8Array(len);
|
|
926
|
-
for (let i = 0; i < len; i++) {
|
|
927
|
-
bytes[i] = parseInt(hex.slice(i * 2, i * 2 + 2), 16);
|
|
928
|
-
}
|
|
929
|
-
return bytes;
|
|
930
|
-
}
|
|
931
|
-
|
|
932
|
-
// src/collection.ts
|
|
933
805
|
var Collection = class {
|
|
934
806
|
constructor(serverUrl, vaultUid, collectionName, encryptionKey, hmacKey, getAuthHeader, httpClient) {
|
|
935
807
|
this.serverUrl = serverUrl;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ursalock/client",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.1",
|
|
4
4
|
"description": "Auth and API client for ursalock with E2EE passkey encryption",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
"typecheck": "tsc --noEmit"
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
|
+
"@ursalock/crypto": "^0.4.0",
|
|
25
26
|
"@z-base/zero-knowledge-credentials": "^1.0.2"
|
|
26
27
|
},
|
|
27
28
|
"peerDependencies": {
|