Skip to content

Commit 03225a2

Browse files
committed
chore: add AESEncryptString api to trust ring
1 parent dc92fd0 commit 03225a2

2 files changed

Lines changed: 88 additions & 0 deletions

File tree

src/phoenix/trust_ring.js

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,47 @@ function generateRandomKeyAndIV() {
119119
return { key, iv };
120120
}
121121

122+
async function AESEncryptString(val, key, iv) {
123+
// Encode string to UTF-8 bytes
124+
const data = new TextEncoder().encode(val);
125+
126+
// Convert hex key to bytes
127+
const keyBytes = new Uint8Array(key.length / 2);
128+
for (let i = 0; i < key.length; i += 2) {
129+
keyBytes[i / 2] = parseInt(key.substr(i, 2), 16);
130+
}
131+
132+
// Convert hex IV to bytes
133+
const ivBytes = new Uint8Array(iv.length / 2);
134+
for (let i = 0; i < iv.length; i += 2) {
135+
ivBytes[i / 2] = parseInt(iv.substr(i, 2), 16);
136+
}
137+
138+
// Import the AES key
139+
const cryptoKey = await crypto.subtle.importKey(
140+
'raw',
141+
keyBytes,
142+
{ name: 'AES-GCM' },
143+
false,
144+
['encrypt']
145+
);
146+
147+
// Encrypt the data
148+
const encryptedBuffer = await crypto.subtle.encrypt(
149+
{
150+
name: 'AES-GCM',
151+
iv: ivBytes
152+
},
153+
cryptoKey,
154+
data
155+
);
156+
157+
// Convert encrypted bytes to hex string
158+
return Array.from(new Uint8Array(encryptedBuffer))
159+
.map(byte => byte.toString(16).padStart(2, '0'))
160+
.join('');
161+
}
162+
122163
async function AESDecryptString(val, key, iv) {
123164
// Convert hex strings to ArrayBuffers
124165
const encryptedData = new Uint8Array(val.length / 2);
@@ -472,6 +513,7 @@ window.KernalModeTrust = {
472513
setCredential,
473514
getCredential,
474515
removeCredential,
516+
AESEncryptString,
475517
AESDecryptString,
476518
generateRandomKeyAndIV,
477519
dismantleKeyring,

test/spec/trust-ring-test.js

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,52 @@ define(function (require, exports, module) {
156156
});
157157
});
158158

159+
describe("AESEncryptString and AESDecryptString", function () {
160+
it("should encrypt then decrypt roundtrip returning original string", async function () {
161+
const {key, iv} = TrustRing.generateRandomKeyAndIV();
162+
const original = "hello world";
163+
const encrypted = await TrustRing.AESEncryptString(original, key, iv);
164+
const decrypted = await TrustRing.AESDecryptString(encrypted, key, iv);
165+
expect(decrypted).toBe(original);
166+
});
167+
168+
it("should produce a hex string output", async function () {
169+
const {key, iv} = TrustRing.generateRandomKeyAndIV();
170+
const encrypted = await TrustRing.AESEncryptString("test", key, iv);
171+
expect(encrypted).toMatch(/^[a-f0-9]+$/);
172+
});
173+
174+
it("should produce different ciphertext for different plaintext", async function () {
175+
const {key, iv} = TrustRing.generateRandomKeyAndIV();
176+
const enc1 = await TrustRing.AESEncryptString("plaintext1", key, iv);
177+
const enc2 = await TrustRing.AESEncryptString("plaintext2", key, iv);
178+
expect(enc1).not.toBe(enc2);
179+
});
180+
181+
it("should work with empty string", async function () {
182+
const {key, iv} = TrustRing.generateRandomKeyAndIV();
183+
const encrypted = await TrustRing.AESEncryptString("", key, iv);
184+
const decrypted = await TrustRing.AESDecryptString(encrypted, key, iv);
185+
expect(decrypted).toBe("");
186+
});
187+
188+
it("should work with unicode characters", async function () {
189+
const {key, iv} = TrustRing.generateRandomKeyAndIV();
190+
const original = "测试数据 with émojis 🔒🔑";
191+
const encrypted = await TrustRing.AESEncryptString(original, key, iv);
192+
const decrypted = await TrustRing.AESDecryptString(encrypted, key, iv);
193+
expect(decrypted).toBe(original);
194+
});
195+
196+
it("should work with large strings", async function () {
197+
const {key, iv} = TrustRing.generateRandomKeyAndIV();
198+
const original = "x".repeat(10000);
199+
const encrypted = await TrustRing.AESEncryptString(original, key, iv);
200+
const decrypted = await TrustRing.AESDecryptString(encrypted, key, iv);
201+
expect(decrypted).toBe(original);
202+
});
203+
});
204+
159205
describe("generateDataSignature and validateDataSignature integration", function () {
160206
it("should work with JSON data like entitlements", async function () {
161207
const entitlements = {

0 commit comments

Comments
 (0)