Skip to content

Commit f947818

Browse files
committed
Update typescript example in 'encryption_ztdf.mdx'
1 parent fe42d0b commit f947818

1 file changed

Lines changed: 167 additions & 41 deletions

File tree

code_samples/tdf/encryption_ztdf.mdx

Lines changed: 167 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -165,47 +165,173 @@ public class EncryptExample {
165165
<TabItem value="js" label="Typescript">
166166

167167
```typescript
168-
import { AuthProviders, NanoTDFClient } from '@opentdf/sdk';
169-
170-
// Configuration Options
171-
const kasEndpoint = "https://kas.example.com";
172-
173-
// Authentication options (vary by middleware)
174-
const oidcOrigin = "https://idp.example.com";
175-
const clientId = "applicationNameFromIdP";
176-
const refreshToken = "userRefreshTokenValueFromIdP";
177-
178-
// AuthProviders are middlewares that add `Authorization` or other bearer tokens to requests.
179-
// These include The `refresh` provider can be handed a refresh and optional access token.
180-
const authProvider = await AuthProviders.refreshAuthProvider({
181-
clientId,
182-
exchange: 'refresh',
183-
refreshToken,
184-
oidcOrigin,
185-
});
186-
187-
const client = new TDF3Client({
188-
authProvider,
189-
kasEndpoint,
190-
});
191-
192-
// ABAC
193-
const attributes = ["http://example.com/attr/classification/value/secret"]
194-
195-
// encrypt
196-
const source = new ReadableStream({
197-
pull(controller) {
198-
controller.enqueue(new TextEncoder().encode(string));
199-
controller.close();
200-
},
201-
});
202-
const ciphertextStream = await client.encrypt({ offline: true, source, scope: {attributes} });
203-
204-
// decrypt
205-
const plaintextStream = await client.decrypt({
206-
source: { type: 'stream', location: ciphertextStream }
207-
});
208-
const plaintext = await plaintextStream.toString();
168+
import { AuthProviders, TDF3Client } from '@opentdf/sdk';
169+
import * as fs from 'fs';
170+
import * as path from 'path';
171+
import * as os from 'os';
172+
173+
async function main() {
174+
try {
175+
console.log("🚀 Starting OpenTDF example...");
176+
177+
// Configuration Options
178+
const platformEndpoint = "http://localhost:8080";
179+
const kasEndpoint = platformEndpoint + "/kas";
180+
const oidcOrigin = "http://localhost:8888/realms/opentdf";
181+
const clientId = "opentdf";
182+
const clientSecret = "secret";
183+
184+
// Authentication options (vary by middleware)
185+
// For client credentials flow
186+
console.log("🔑 Setting up authentication...");
187+
const authProvider = await AuthProviders.clientSecretAuthProvider({
188+
clientId,
189+
clientSecret,
190+
exchange: 'client',
191+
oidcOrigin,
192+
});
193+
console.log("✅ Authentication provider created");
194+
195+
console.log("🔧 Creating TDF3 client...");
196+
const client = new TDF3Client({
197+
authProvider,
198+
kasEndpoint,
199+
platformUrl: platformEndpoint, // Required for decryption
200+
});
201+
console.log("✅ TDF3 client created");
202+
203+
// ABAC - Attribute-Based Access Control
204+
// Option 1: No attributes (simplest for demonstration)
205+
const attributes: string[] = [];
206+
207+
// Option 2: With attributes (requires proper attribute configuration on platform)
208+
// const attributes = ["http://example.com/attr/classification/value/secret"];
209+
// Note: When using attributes, ensure they are properly configured on the platform
210+
// and the client has appropriate permissions
211+
212+
// Create temporary files
213+
const tempDir = os.tmpdir();
214+
const inputFile = path.join(tempDir, 'opentdf-input.txt');
215+
const encryptedFile = path.join(tempDir, 'opentdf-encrypted.tdf');
216+
const decryptedFile = path.join(tempDir, 'opentdf-decrypted.txt');
217+
218+
console.log(`📁 Using temp files:`);
219+
console.log(` Input: ${inputFile}`);
220+
console.log(` Encrypted: ${encryptedFile}`);
221+
console.log(` Decrypted: ${decryptedFile}`);
222+
223+
// Write input data to temporary file
224+
const inputData = "This is sensitive data that will be encrypted with OpenTDF!";
225+
console.log("📝 Writing input data to temp file...");
226+
fs.writeFileSync(inputFile, inputData, 'utf8');
227+
console.log(`✅ Input file written: ${inputData}`);
228+
229+
// Encrypt
230+
console.log("🔒 Starting encryption...");
231+
console.log("📖 Reading input file for encryption...");
232+
233+
// Read the file and create a Web ReadableStream
234+
const inputBuffer = fs.readFileSync(inputFile);
235+
const source = new ReadableStream({
236+
start(controller) {
237+
controller.enqueue(inputBuffer);
238+
controller.close();
239+
}
240+
});
241+
242+
console.log("📡 Calling client.encrypt...");
243+
const ciphertextStream = await client.encrypt({
244+
offline: true,
245+
source,
246+
scope: { attributes }
247+
});
248+
249+
// Save encrypted stream to file
250+
console.log("💾 Saving encrypted data to temp file...");
251+
252+
// Use the toBuffer() method which is available on DecoratedReadableStream
253+
try {
254+
const encryptedBuffer = await (ciphertextStream as any).toBuffer();
255+
fs.writeFileSync(encryptedFile, encryptedBuffer);
256+
console.log("✅ Used toBuffer() method to save encrypted data");
257+
} catch (err) {
258+
console.log("❌ toBuffer() failed, trying toString():", err);
259+
260+
// Fallback to toString method
261+
const encryptedString = await (ciphertextStream as any).toString();
262+
const encryptedData = Buffer.from(encryptedString, 'binary');
263+
fs.writeFileSync(encryptedFile, encryptedData);
264+
console.log("✅ Used toString() method to save encrypted data");
265+
}
266+
267+
console.log('✅ Data encrypted and saved to file!');
268+
269+
// Note: You may see a "Mismatched wrapping key algorithm" warning above.
270+
// This is a known issue where the SDK doesn't specify the algorithm preference
271+
// when requesting keys, but it doesn't prevent successful encryption/decryption.
272+
273+
// Now decrypt the file
274+
console.log("🔓 Starting decryption...");
275+
console.log("📖 Reading encrypted file for decryption...");
276+
277+
// Read the encrypted file as buffer and provide it in the correct format for the SDK
278+
const savedEncryptedData = fs.readFileSync(encryptedFile);
279+
280+
console.log("📡 Calling client.decrypt...");
281+
const plaintextStream = await client.decrypt({
282+
source: { type: 'buffer', location: savedEncryptedData }
283+
});
284+
285+
// Save decrypted stream to file
286+
console.log("💾 Saving decrypted data to temp file...");
287+
288+
// Use the toBuffer() method for the plaintext stream as well
289+
try {
290+
const decryptedBuffer = await (plaintextStream as any).toBuffer();
291+
fs.writeFileSync(decryptedFile, decryptedBuffer);
292+
console.log("✅ Used toBuffer() method to save decrypted data");
293+
} catch (err) {
294+
console.log("❌ toBuffer() failed, trying toString():", err);
295+
296+
// Fallback to toString method
297+
const decryptedString = await (plaintextStream as any).toString();
298+
const decryptedData = Buffer.from(decryptedString, 'utf8');
299+
fs.writeFileSync(decryptedFile, decryptedData);
300+
console.log("✅ Used toString() method to save decrypted data");
301+
}
302+
303+
// Read and display the decrypted content
304+
const decryptedContent = fs.readFileSync(decryptedFile, 'utf8');
305+
console.log('✅ Data decrypted and saved to file!');
306+
console.log(`📤 Decrypted content: "${decryptedContent}"`);
307+
308+
// Verify the round-trip worked
309+
if (inputData === decryptedContent) {
310+
console.log('🎉 SUCCESS: Input and decrypted data match perfectly!');
311+
} else {
312+
console.log('❌ ERROR: Input and decrypted data do not match!');
313+
console.log(`Original: "${inputData}"`);
314+
console.log(`Decrypted: "${decryptedContent}"`);
315+
}
316+
317+
// Clean up temporary files
318+
console.log("🧹 Cleaning up temporary files...");
319+
try {
320+
fs.unlinkSync(inputFile);
321+
fs.unlinkSync(encryptedFile);
322+
fs.unlinkSync(decryptedFile);
323+
console.log("✅ Temporary files cleaned up");
324+
} catch (cleanupErr) {
325+
console.log("⚠️ Warning: Could not clean up some temporary files:", cleanupErr);
326+
}
327+
} catch (err) {
328+
console.error('Error in OpenTDF example:', err);
329+
}
330+
}
331+
332+
// Run the example
333+
main();
334+
209335
```
210336

211337
</TabItem>

0 commit comments

Comments
 (0)