@vollcrypt/messages-wasm 0.2.0
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/README.md +57 -0
- package/fast.d.ts +102 -0
- package/fast.js +301 -0
- package/package.json +41 -0
package/README.md
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# @vollcrypt/wasm
|
|
2
|
+
|
|
3
|
+
**Cross-platform, quantum-resistant cryptography engine - WebAssembly Binding**
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/@vollcrypt/wasm)
|
|
6
|
+
[](https://github.com/BeratVural/vollcrypt/blob/main/LICENSE)
|
|
7
|
+
|
|
8
|
+
This package provides the **WebAssembly (WASM) bindings** for the Vollcrypt cryptography engine. It is compiled directly from Rust using `wasm-pack`, bringing robust, post-quantum cryptography straight to the user's browser or frontend application (React, Next.js, Vue, etc.) without relying on slow JavaScript cryptography implementations.
|
|
9
|
+
|
|
10
|
+
## Features
|
|
11
|
+
|
|
12
|
+
- **Universal:** Runs in any modern browser without native binary dependencies.
|
|
13
|
+
- **Quantum-Resistant:** Implements the NIST FIPS 203 (ML-KEM-768) standard combined with X25519 for hybrid key exchange.
|
|
14
|
+
- **Client-Side E2EE:** Perfect for End-to-End Encryption where keys never leave the user's device.
|
|
15
|
+
- **Secure Defaults:** Provides AES-256-GCM, Ed25519, HKDF-SHA256, and post-compromise security ratchets out of the box.
|
|
16
|
+
|
|
17
|
+
## Installation
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
npm install @vollcrypt/wasm
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
*Note: Since this is a WebAssembly module, you may need to configure your bundler (Webpack, Vite, Rollup) to handle `.wasm` files depending on your frontend setup.*
|
|
24
|
+
|
|
25
|
+
## Quick Start
|
|
26
|
+
|
|
27
|
+
```javascript
|
|
28
|
+
import * as vollcrypt from '@vollcrypt/wasm';
|
|
29
|
+
|
|
30
|
+
// Generate an Ed25519 Identity Keypair
|
|
31
|
+
const identity = vollcrypt.generate_ed25519_keypair();
|
|
32
|
+
console.log("Public Key:", Buffer.from(identity.public_key).toString('hex'));
|
|
33
|
+
|
|
34
|
+
// Sign and Verify
|
|
35
|
+
const message = new TextEncoder().encode("Hello from Vollcrypt WASM!");
|
|
36
|
+
const signature = vollcrypt.sign_message(identity.private_key, message);
|
|
37
|
+
const isValid = vollcrypt.verify_signature(identity.public_key, message, signature);
|
|
38
|
+
|
|
39
|
+
console.log("Signature Valid:", isValid); // true
|
|
40
|
+
|
|
41
|
+
// Hybrid Key Exchange (X25519)
|
|
42
|
+
const alice = vollcrypt.generate_x25519_keypair();
|
|
43
|
+
const bob = vollcrypt.generate_x25519_keypair();
|
|
44
|
+
const sharedSecret = vollcrypt.ecdh_shared_secret(alice.private_key, bob.public_key);
|
|
45
|
+
|
|
46
|
+
console.log("Shared Secret Derived successfully.");
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Documentation
|
|
50
|
+
|
|
51
|
+
For full API documentation, architecture details, and the high-performance Native Node.js equivalent, please refer to the [Vollcrypt Main Repository](https://github.com/BeratVural/vollcrypt).
|
|
52
|
+
|
|
53
|
+
## License
|
|
54
|
+
|
|
55
|
+
This project is licensed under the **GNU General Public License v3.0**.
|
|
56
|
+
|
|
57
|
+
For commercial use without the GPL copyleft requirement, please contact Berat Vural at [berat.vural.tr@gmail.com](mailto:berat.vural.tr@gmail.com).
|
package/fast.d.ts
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
export { default } from "./pkg/wasm"
|
|
2
|
+
export * from "./pkg/wasm"
|
|
3
|
+
|
|
4
|
+
export declare function encryptAesGcmWeb(
|
|
5
|
+
key: CryptoKey | Uint8Array,
|
|
6
|
+
plaintext: Uint8Array,
|
|
7
|
+
aad?: Uint8Array | null
|
|
8
|
+
): Promise<Uint8Array>
|
|
9
|
+
|
|
10
|
+
export declare function decryptAesGcmWeb(
|
|
11
|
+
key: CryptoKey | Uint8Array,
|
|
12
|
+
ciphertext: Uint8Array,
|
|
13
|
+
aad?: Uint8Array | null
|
|
14
|
+
): Promise<Uint8Array>
|
|
15
|
+
|
|
16
|
+
export declare function encryptAesGcmAuto(
|
|
17
|
+
key: CryptoKey | Uint8Array,
|
|
18
|
+
plaintext: Uint8Array,
|
|
19
|
+
aad?: Uint8Array | null
|
|
20
|
+
): Promise<Uint8Array>
|
|
21
|
+
|
|
22
|
+
export declare function decryptAesGcmAuto(
|
|
23
|
+
key: CryptoKey | Uint8Array,
|
|
24
|
+
ciphertext: Uint8Array,
|
|
25
|
+
aad?: Uint8Array | null
|
|
26
|
+
): Promise<Uint8Array>
|
|
27
|
+
|
|
28
|
+
export declare function encryptAesGcmPaddedWeb(
|
|
29
|
+
key: CryptoKey | Uint8Array,
|
|
30
|
+
plaintext: Uint8Array,
|
|
31
|
+
aad?: Uint8Array | null
|
|
32
|
+
): Promise<Uint8Array>
|
|
33
|
+
|
|
34
|
+
export declare function decryptAesGcmPaddedWeb(
|
|
35
|
+
key: CryptoKey | Uint8Array,
|
|
36
|
+
ciphertext: Uint8Array,
|
|
37
|
+
aad?: Uint8Array | null
|
|
38
|
+
): Promise<Uint8Array>
|
|
39
|
+
|
|
40
|
+
export declare function encryptAesGcmPaddedAuto(
|
|
41
|
+
key: CryptoKey | Uint8Array,
|
|
42
|
+
plaintext: Uint8Array,
|
|
43
|
+
aad?: Uint8Array | null
|
|
44
|
+
): Promise<Uint8Array>
|
|
45
|
+
|
|
46
|
+
export declare function decryptAesGcmPaddedAuto(
|
|
47
|
+
key: CryptoKey | Uint8Array,
|
|
48
|
+
ciphertext: Uint8Array,
|
|
49
|
+
aad?: Uint8Array | null
|
|
50
|
+
): Promise<Uint8Array>
|
|
51
|
+
|
|
52
|
+
export declare function encryptAesGcmChunkedWeb(
|
|
53
|
+
key: CryptoKey | Uint8Array,
|
|
54
|
+
plaintext: Uint8Array,
|
|
55
|
+
aad: Uint8Array | null | undefined,
|
|
56
|
+
chunkSize: number
|
|
57
|
+
): Promise<Uint8Array>
|
|
58
|
+
|
|
59
|
+
export declare function decryptAesGcmChunkedWeb(
|
|
60
|
+
key: CryptoKey | Uint8Array,
|
|
61
|
+
ciphertext: Uint8Array,
|
|
62
|
+
aad: Uint8Array | null | undefined
|
|
63
|
+
): Promise<Uint8Array>
|
|
64
|
+
|
|
65
|
+
export declare function encryptAesGcmChunkedPaddedWeb(
|
|
66
|
+
key: CryptoKey | Uint8Array,
|
|
67
|
+
plaintext: Uint8Array,
|
|
68
|
+
aad: Uint8Array | null | undefined,
|
|
69
|
+
chunkSize: number
|
|
70
|
+
): Promise<Uint8Array>
|
|
71
|
+
|
|
72
|
+
export declare function decryptAesGcmChunkedPaddedWeb(
|
|
73
|
+
key: CryptoKey | Uint8Array,
|
|
74
|
+
ciphertext: Uint8Array,
|
|
75
|
+
aad: Uint8Array | null | undefined
|
|
76
|
+
): Promise<Uint8Array>
|
|
77
|
+
|
|
78
|
+
export declare function encryptAesGcmChunkedAuto(
|
|
79
|
+
key: CryptoKey | Uint8Array,
|
|
80
|
+
plaintext: Uint8Array,
|
|
81
|
+
aad: Uint8Array | null | undefined,
|
|
82
|
+
chunkSize: number
|
|
83
|
+
): Promise<Uint8Array>
|
|
84
|
+
|
|
85
|
+
export declare function decryptAesGcmChunkedAuto(
|
|
86
|
+
key: CryptoKey | Uint8Array,
|
|
87
|
+
ciphertext: Uint8Array,
|
|
88
|
+
aad: Uint8Array | null | undefined
|
|
89
|
+
): Promise<Uint8Array>
|
|
90
|
+
|
|
91
|
+
export declare function encryptAesGcmChunkedPaddedAuto(
|
|
92
|
+
key: CryptoKey | Uint8Array,
|
|
93
|
+
plaintext: Uint8Array,
|
|
94
|
+
aad: Uint8Array | null | undefined,
|
|
95
|
+
chunkSize: number
|
|
96
|
+
): Promise<Uint8Array>
|
|
97
|
+
|
|
98
|
+
export declare function decryptAesGcmChunkedPaddedAuto(
|
|
99
|
+
key: CryptoKey | Uint8Array,
|
|
100
|
+
ciphertext: Uint8Array,
|
|
101
|
+
aad: Uint8Array | null | undefined
|
|
102
|
+
): Promise<Uint8Array>
|
package/fast.js
ADDED
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
import init, * as wasm from "./pkg/wasm.js"
|
|
2
|
+
|
|
3
|
+
function getSubtle() {
|
|
4
|
+
const cryptoObj = globalThis?.crypto
|
|
5
|
+
return cryptoObj && cryptoObj.subtle ? cryptoObj.subtle : null
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
function normalizeU8(data) {
|
|
9
|
+
if (data == null) return null
|
|
10
|
+
return data instanceof Uint8Array ? data : new Uint8Array(data)
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
async function importAesKey(key, usages) {
|
|
14
|
+
if (typeof CryptoKey !== "undefined" && key instanceof CryptoKey) {
|
|
15
|
+
return key
|
|
16
|
+
}
|
|
17
|
+
const subtle = getSubtle()
|
|
18
|
+
if (!subtle) {
|
|
19
|
+
throw new Error("WebCrypto not available")
|
|
20
|
+
}
|
|
21
|
+
const raw = normalizeU8(key)
|
|
22
|
+
if (!raw) {
|
|
23
|
+
throw new Error("Invalid key")
|
|
24
|
+
}
|
|
25
|
+
return await subtle.importKey("raw", raw, { name: "AES-GCM" }, false, usages)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export async function encryptAesGcmWeb(key, plaintext, aad) {
|
|
29
|
+
const subtle = getSubtle()
|
|
30
|
+
if (!subtle) {
|
|
31
|
+
throw new Error("WebCrypto not available")
|
|
32
|
+
}
|
|
33
|
+
const pt = normalizeU8(plaintext)
|
|
34
|
+
if (!pt) {
|
|
35
|
+
throw new Error("Invalid plaintext")
|
|
36
|
+
}
|
|
37
|
+
const aadU8 = normalizeU8(aad)
|
|
38
|
+
const cryptoKey = await importAesKey(key, ["encrypt"])
|
|
39
|
+
const iv = new Uint8Array(12)
|
|
40
|
+
globalThis.crypto.getRandomValues(iv)
|
|
41
|
+
const algo = { name: "AES-GCM", iv }
|
|
42
|
+
if (aadU8 && aadU8.length > 0) {
|
|
43
|
+
algo.additionalData = aadU8
|
|
44
|
+
}
|
|
45
|
+
const ct = await subtle.encrypt(algo, cryptoKey, pt)
|
|
46
|
+
const out = new Uint8Array(iv.length + ct.byteLength)
|
|
47
|
+
out.set(iv, 0)
|
|
48
|
+
out.set(new Uint8Array(ct), iv.length)
|
|
49
|
+
return out
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export async function decryptAesGcmWeb(key, ciphertext, aad) {
|
|
53
|
+
const subtle = getSubtle()
|
|
54
|
+
if (!subtle) {
|
|
55
|
+
throw new Error("WebCrypto not available")
|
|
56
|
+
}
|
|
57
|
+
const ct = normalizeU8(ciphertext)
|
|
58
|
+
if (!ct || ct.length < 12) {
|
|
59
|
+
throw new Error("Ciphertext too short")
|
|
60
|
+
}
|
|
61
|
+
const aadU8 = normalizeU8(aad)
|
|
62
|
+
const cryptoKey = await importAesKey(key, ["decrypt"])
|
|
63
|
+
const iv = ct.slice(0, 12)
|
|
64
|
+
const data = ct.slice(12)
|
|
65
|
+
const algo = { name: "AES-GCM", iv }
|
|
66
|
+
if (aadU8 && aadU8.length > 0) {
|
|
67
|
+
algo.additionalData = aadU8
|
|
68
|
+
}
|
|
69
|
+
const pt = await subtle.decrypt(algo, cryptoKey, data)
|
|
70
|
+
return new Uint8Array(pt)
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export async function encryptAesGcmAuto(key, plaintext, aad) {
|
|
74
|
+
const subtle = getSubtle()
|
|
75
|
+
if (subtle) {
|
|
76
|
+
return await encryptAesGcmWeb(key, plaintext, aad)
|
|
77
|
+
}
|
|
78
|
+
return wasm.encryptAesGcm(key, plaintext, aad ?? null)
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export async function decryptAesGcmAuto(key, ciphertext, aad) {
|
|
82
|
+
const subtle = getSubtle()
|
|
83
|
+
if (subtle) {
|
|
84
|
+
return await decryptAesGcmWeb(key, ciphertext, aad)
|
|
85
|
+
}
|
|
86
|
+
return wasm.decryptAesGcm(key, ciphertext, aad ?? null)
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function calculatePaddingLen(contentLen) {
|
|
90
|
+
const sizes = [64, 128, 256, 512, 1024, 2048]
|
|
91
|
+
const minPadding = 2
|
|
92
|
+
const target = sizes.find((s) => s >= contentLen + minPadding) ?? (() => {
|
|
93
|
+
const remainder = (contentLen + minPadding) % 1024
|
|
94
|
+
return remainder === 0 ? contentLen + minPadding : contentLen + minPadding + (1024 - remainder)
|
|
95
|
+
})()
|
|
96
|
+
return target - contentLen
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function padWithLen(content) {
|
|
100
|
+
const pt = normalizeU8(content)
|
|
101
|
+
if (!pt) {
|
|
102
|
+
throw new Error("Invalid plaintext")
|
|
103
|
+
}
|
|
104
|
+
if (pt.length > 0xffffffff) {
|
|
105
|
+
throw new Error("Message too large to pad")
|
|
106
|
+
}
|
|
107
|
+
const lenPrefix = new Uint8Array(4)
|
|
108
|
+
new DataView(lenPrefix.buffer).setUint32(0, pt.length, false)
|
|
109
|
+
const baseLen = 4 + pt.length
|
|
110
|
+
const padLen = calculatePaddingLen(baseLen)
|
|
111
|
+
const padding = new Uint8Array(padLen)
|
|
112
|
+
if (padLen > 0) {
|
|
113
|
+
globalThis.crypto.getRandomValues(padding)
|
|
114
|
+
}
|
|
115
|
+
const out = new Uint8Array(baseLen + padLen)
|
|
116
|
+
out.set(lenPrefix, 0)
|
|
117
|
+
out.set(pt, 4)
|
|
118
|
+
out.set(padding, 4 + pt.length)
|
|
119
|
+
return out
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function unpadWithLen(padded) {
|
|
123
|
+
const buf = normalizeU8(padded)
|
|
124
|
+
if (!buf || buf.length < 4) {
|
|
125
|
+
throw new Error("Padded message too short")
|
|
126
|
+
}
|
|
127
|
+
const len = new DataView(buf.buffer, buf.byteOffset, buf.byteLength).getUint32(0, false)
|
|
128
|
+
if (len > buf.length - 4) {
|
|
129
|
+
throw new Error("Invalid padded message length")
|
|
130
|
+
}
|
|
131
|
+
return buf.subarray(4, 4 + len)
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
export async function encryptAesGcmPaddedWeb(key, plaintext, aad) {
|
|
135
|
+
const padded = padWithLen(plaintext)
|
|
136
|
+
return await encryptAesGcmWeb(key, padded, aad)
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export async function decryptAesGcmPaddedWeb(key, ciphertext, aad) {
|
|
140
|
+
const padded = await decryptAesGcmWeb(key, ciphertext, aad)
|
|
141
|
+
return unpadWithLen(padded)
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
export async function encryptAesGcmPaddedAuto(key, plaintext, aad) {
|
|
145
|
+
const subtle = getSubtle()
|
|
146
|
+
if (subtle) {
|
|
147
|
+
return await encryptAesGcmPaddedWeb(key, plaintext, aad)
|
|
148
|
+
}
|
|
149
|
+
return wasm.encryptAesGcmPadded(key, plaintext, aad ?? null)
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
export async function decryptAesGcmPaddedAuto(key, ciphertext, aad) {
|
|
153
|
+
const subtle = getSubtle()
|
|
154
|
+
if (subtle) {
|
|
155
|
+
return await decryptAesGcmPaddedWeb(key, ciphertext, aad)
|
|
156
|
+
}
|
|
157
|
+
return wasm.decryptAesGcmPadded(key, ciphertext, aad ?? null)
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
function buildChunkAad(baseAad, chunkIndex) {
|
|
161
|
+
const aadPrefix = baseAad ? normalizeU8(baseAad) : null
|
|
162
|
+
const indexBuf = new Uint8Array(4)
|
|
163
|
+
const view = new DataView(indexBuf.buffer)
|
|
164
|
+
view.setUint32(0, chunkIndex, false)
|
|
165
|
+
if (!aadPrefix || aadPrefix.length === 0) {
|
|
166
|
+
return indexBuf
|
|
167
|
+
}
|
|
168
|
+
const out = new Uint8Array(aadPrefix.length + 4)
|
|
169
|
+
out.set(aadPrefix, 0)
|
|
170
|
+
out.set(indexBuf, aadPrefix.length)
|
|
171
|
+
return out
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
export async function encryptAesGcmChunkedWeb(key, plaintext, aad, chunkSize) {
|
|
175
|
+
if (!chunkSize || chunkSize <= 0) {
|
|
176
|
+
throw new Error("Invalid chunk size")
|
|
177
|
+
}
|
|
178
|
+
const pt = normalizeU8(plaintext)
|
|
179
|
+
if (!pt) {
|
|
180
|
+
throw new Error("Invalid plaintext")
|
|
181
|
+
}
|
|
182
|
+
const totalLen = pt.length
|
|
183
|
+
const chunkCount = totalLen === 0 ? 1 : Math.ceil(totalLen / chunkSize)
|
|
184
|
+
if (chunkCount > 0xffffffff) {
|
|
185
|
+
throw new Error("Chunk count exceeds supported maximum")
|
|
186
|
+
}
|
|
187
|
+
const parts = []
|
|
188
|
+
const header = new Uint8Array(4)
|
|
189
|
+
new DataView(header.buffer).setUint32(0, chunkCount, false)
|
|
190
|
+
parts.push(header)
|
|
191
|
+
for (let i = 0; i < chunkCount; i += 1) {
|
|
192
|
+
const start = i * chunkSize
|
|
193
|
+
const end = totalLen === 0 ? 0 : Math.min(start + chunkSize, totalLen)
|
|
194
|
+
const chunk = pt.subarray(start, end)
|
|
195
|
+
const aadChunk = buildChunkAad(aad, i)
|
|
196
|
+
const enc = await encryptAesGcmWeb(key, chunk, aadChunk)
|
|
197
|
+
const h = new Uint8Array(8)
|
|
198
|
+
const v = new DataView(h.buffer)
|
|
199
|
+
v.setUint32(0, i, false)
|
|
200
|
+
v.setUint32(4, enc.length, false)
|
|
201
|
+
parts.push(h, enc)
|
|
202
|
+
if (totalLen === 0) break
|
|
203
|
+
}
|
|
204
|
+
const total = parts.reduce((sum, p) => sum + p.length, 0)
|
|
205
|
+
const out = new Uint8Array(total)
|
|
206
|
+
let offset = 0
|
|
207
|
+
for (const p of parts) {
|
|
208
|
+
out.set(p, offset)
|
|
209
|
+
offset += p.length
|
|
210
|
+
}
|
|
211
|
+
return out
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
export async function encryptAesGcmChunkedPaddedWeb(key, plaintext, aad, chunkSize) {
|
|
215
|
+
const padded = padWithLen(plaintext)
|
|
216
|
+
return await encryptAesGcmChunkedWeb(key, padded, aad, chunkSize)
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
export async function decryptAesGcmChunkedWeb(key, ciphertext, aad) {
|
|
220
|
+
const ct = normalizeU8(ciphertext)
|
|
221
|
+
if (!ct || ct.length < 4) {
|
|
222
|
+
throw new Error("Encrypted data too short")
|
|
223
|
+
}
|
|
224
|
+
const view = new DataView(ct.buffer, ct.byteOffset, ct.byteLength)
|
|
225
|
+
const chunkCount = view.getUint32(0, false)
|
|
226
|
+
if (chunkCount === 0) {
|
|
227
|
+
throw new Error("Invalid chunk count")
|
|
228
|
+
}
|
|
229
|
+
let offset = 4
|
|
230
|
+
const parts = []
|
|
231
|
+
for (let expected = 0; expected < chunkCount; expected += 1) {
|
|
232
|
+
if (offset + 8 > ct.length) {
|
|
233
|
+
throw new Error("Encrypted data truncated")
|
|
234
|
+
}
|
|
235
|
+
const chunkIndex = view.getUint32(offset, false)
|
|
236
|
+
const chunkLen = view.getUint32(offset + 4, false)
|
|
237
|
+
offset += 8
|
|
238
|
+
if (chunkIndex !== expected) {
|
|
239
|
+
throw new Error("Chunk index mismatch")
|
|
240
|
+
}
|
|
241
|
+
if (chunkLen === 0 || offset + chunkLen > ct.length) {
|
|
242
|
+
throw new Error("Invalid chunk length")
|
|
243
|
+
}
|
|
244
|
+
const chunk = ct.subarray(offset, offset + chunkLen)
|
|
245
|
+
const aadChunk = buildChunkAad(aad, chunkIndex)
|
|
246
|
+
const dec = await decryptAesGcmWeb(key, chunk, aadChunk)
|
|
247
|
+
parts.push(dec)
|
|
248
|
+
offset += chunkLen
|
|
249
|
+
}
|
|
250
|
+
if (offset !== ct.length) {
|
|
251
|
+
throw new Error("Trailing data after chunks")
|
|
252
|
+
}
|
|
253
|
+
const total = parts.reduce((sum, p) => sum + p.length, 0)
|
|
254
|
+
const out = new Uint8Array(total)
|
|
255
|
+
let outOffset = 0
|
|
256
|
+
for (const p of parts) {
|
|
257
|
+
out.set(p, outOffset)
|
|
258
|
+
outOffset += p.length
|
|
259
|
+
}
|
|
260
|
+
return out
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
export async function decryptAesGcmChunkedPaddedWeb(key, ciphertext, aad) {
|
|
264
|
+
const padded = await decryptAesGcmChunkedWeb(key, ciphertext, aad)
|
|
265
|
+
return unpadWithLen(padded)
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
export async function encryptAesGcmChunkedAuto(key, plaintext, aad, chunkSize) {
|
|
269
|
+
const subtle = getSubtle()
|
|
270
|
+
if (subtle) {
|
|
271
|
+
return await encryptAesGcmChunkedWeb(key, plaintext, aad, chunkSize)
|
|
272
|
+
}
|
|
273
|
+
return wasm.encryptAesGcmChunked(key, plaintext, aad ?? null, chunkSize)
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
export async function encryptAesGcmChunkedPaddedAuto(key, plaintext, aad, chunkSize) {
|
|
277
|
+
const subtle = getSubtle()
|
|
278
|
+
if (subtle) {
|
|
279
|
+
return await encryptAesGcmChunkedPaddedWeb(key, plaintext, aad, chunkSize)
|
|
280
|
+
}
|
|
281
|
+
return wasm.encryptAesGcmChunkedPadded(key, plaintext, aad ?? null, chunkSize)
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
export async function decryptAesGcmChunkedAuto(key, ciphertext, aad) {
|
|
285
|
+
const subtle = getSubtle()
|
|
286
|
+
if (subtle) {
|
|
287
|
+
return await decryptAesGcmChunkedWeb(key, ciphertext, aad)
|
|
288
|
+
}
|
|
289
|
+
return wasm.decryptAesGcmChunked(key, ciphertext, aad ?? null)
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
export async function decryptAesGcmChunkedPaddedAuto(key, ciphertext, aad) {
|
|
293
|
+
const subtle = getSubtle()
|
|
294
|
+
if (subtle) {
|
|
295
|
+
return await decryptAesGcmChunkedPaddedWeb(key, ciphertext, aad)
|
|
296
|
+
}
|
|
297
|
+
return wasm.decryptAesGcmChunkedPadded(key, ciphertext, aad ?? null)
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
export { init }
|
|
301
|
+
export * from "./pkg/wasm.js"
|
package/package.json
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@vollcrypt/messages-wasm",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "Cross-platform, quantum-resistant cryptography engine - WebAssembly binding",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "pkg/wasm.js",
|
|
7
|
+
"types": "pkg/wasm.d.ts",
|
|
8
|
+
"publishConfig": {
|
|
9
|
+
"access": "public"
|
|
10
|
+
},
|
|
11
|
+
"repository": {
|
|
12
|
+
"type": "git",
|
|
13
|
+
"url": "git+https://github.com/BeratVural/vollcrypt.git",
|
|
14
|
+
"directory": "wasm"
|
|
15
|
+
},
|
|
16
|
+
"homepage": "https://github.com/BeratVural/vollcrypt#readme",
|
|
17
|
+
"bugs": {
|
|
18
|
+
"url": "https://github.com/BeratVural/vollcrypt/issues"
|
|
19
|
+
},
|
|
20
|
+
"files": [
|
|
21
|
+
"pkg/",
|
|
22
|
+
"fast.js",
|
|
23
|
+
"fast.d.ts"
|
|
24
|
+
],
|
|
25
|
+
"keywords": [
|
|
26
|
+
"vollcrypt",
|
|
27
|
+
"cryptography",
|
|
28
|
+
"encryption",
|
|
29
|
+
"wasm",
|
|
30
|
+
"webassembly",
|
|
31
|
+
"aes-gcm",
|
|
32
|
+
"ed25519",
|
|
33
|
+
"x25519",
|
|
34
|
+
"ml-kem",
|
|
35
|
+
"post-quantum",
|
|
36
|
+
"pqc",
|
|
37
|
+
"e2ee"
|
|
38
|
+
],
|
|
39
|
+
"author": "Berat Vural <berat.vural.tr@gmail.com>",
|
|
40
|
+
"license": "GPL-3.0-only"
|
|
41
|
+
}
|