Documentation Index
Fetch the complete documentation index at: https://mintlify.com/amark/gun/llms.txt
Use this file to discover all available pages before exploring further.
SEA.decrypt()
Decrypt data that was encrypted with SEA.encrypt(). Requires the same key that was used for encryption.
Syntax
const decrypted = await SEA.decrypt(encrypted, key)
SEA.decrypt(encrypted, key, callback)
SEA.decrypt(encrypted, key, callback, options)
Parameters
- encrypted (string|object): Encrypted data from
SEA.encrypt()
- key (string|object): Decryption key or key pair with
epriv property
- callback (function, optional): Called with decrypted result
- options (object, optional):
encode: Encoding of encrypted data (default: ‘base64’)
name: Decryption algorithm (default: ‘AES-GCM’)
Returns
A Promise that resolves to the decrypted data in its original format.
Basic Usage
Decrypt with Password
const encrypted = await SEA.encrypt('secret', 'password');
const decrypted = await SEA.decrypt(encrypted, 'password');
console.log(decrypted); // 'secret'
Decrypt with Key Pair
const pair = await SEA.pair();
const encrypted = await SEA.encrypt('data', pair);
const decrypted = await SEA.decrypt(encrypted, pair);
console.log(decrypted); // 'data'
With Callback
SEA.decrypt(encrypted, 'password', (decrypted) => {
if (decrypted) {
console.log('Decrypted:', decrypted);
} else {
console.error('Decryption failed');
}
});
How It Works
Reference: ~/workspace/source/sea/decrypt.js:8-40
- Parse Encrypted Data: Extracts
ct, iv, and s from encrypted string/object
- Decode: Converts base64 strings to binary buffers
- Derive Key: Reconstructs AES key from input key + salt
- Decrypt: Uses AES-GCM to decrypt ciphertext
- Parse Result: Converts decrypted data back to original format
Decryption Process
// 1. Parse encrypted data
const { ct, iv, s } = parseEncrypted(encrypted);
// 2. Derive same AES key used for encryption
const aesKey = await deriveKey(key, s);
// 3. Decrypt
const decrypted = await crypto.subtle.decrypt(
{
name: 'AES-GCM',
iv: iv,
tagLength: 128
},
aesKey,
ct
);
// 4. Parse result (JSON if object, string otherwise)
return parse(decrypted);
const encrypted = 'SEA{"ct":"...","iv":"...","s":"..."}';
const decrypted = await SEA.decrypt(encrypted, key);
const encrypted = {
ct: 'base64_ciphertext',
iv: 'base64_iv',
s: 'base64_salt'
};
const decrypted = await SEA.decrypt(encrypted, key);
Decryption Key Types
Using a Password
const decrypted = await SEA.decrypt(encrypted, 'same-password-used-to-encrypt');
Using Key Pair
const pair = await SEA.pair();
// Encrypted with this pair
const encrypted = await SEA.encrypt(data, pair);
// Decrypt with same pair
const decrypted = await SEA.decrypt(encrypted, pair);
Using epriv Directly
const decrypted = await SEA.decrypt(encrypted, pair.epriv);
Using Shared Secret
const alice = await SEA.pair();
const bob = await SEA.pair();
// Alice encrypts
const secret = await SEA.secret(bob.epub, alice);
const encrypted = await SEA.encrypt('message', secret);
// Bob decrypts
const bobSecret = await SEA.secret(alice.epub, bob);
const decrypted = await SEA.decrypt(encrypted, bobSecret);
console.log(decrypted); // 'message'
Data Type Preservation
Decryption restores the original data type:
Strings
const encrypted = await SEA.encrypt('Hello', key);
const decrypted = await SEA.decrypt(encrypted, key);
console.log(typeof decrypted); // 'string'
Objects
const encrypted = await SEA.encrypt({ name: 'Alice' }, key);
const decrypted = await SEA.decrypt(encrypted, key);
console.log(decrypted.name); // 'Alice'
Arrays
const encrypted = await SEA.encrypt([1, 2, 3], key);
const decrypted = await SEA.decrypt(encrypted, key);
console.log(Array.isArray(decrypted)); // true
Numbers
const encrypted = await SEA.encrypt(42, key);
const decrypted = await SEA.decrypt(encrypted, key);
console.log(typeof decrypted); // 'number'
Error Handling
Wrong Key
try {
const decrypted = await SEA.decrypt(encrypted, 'wrong-key');
} catch (err) {
console.error('Could not decrypt'); // Wrong key fails silently or throws
}
With Callbacks
SEA.decrypt(encrypted, key, (result) => {
if (!result) {
console.error('Decryption failed - wrong key or corrupted data');
return;
}
console.log('Success:', result);
});
Corrupted Data
try {
const decrypted = await SEA.decrypt('invalid-data', key);
} catch (err) {
console.error('Malformed encrypted data');
}
Decryption failures often return undefined rather than throwing errors. Always check the result before using it.
Options
Custom Encoding
If data was encrypted with custom encoding:
const encrypted = await SEA.encrypt(data, key, null, { encode: 'hex' });
const decrypted = await SEA.decrypt(encrypted, key, null, { encode: 'hex' });
Fallback Encoding
Reference: ~/workspace/source/sea/decrypt.js:24-28
SEA automatically falls back to ‘utf8’ encoding for legacy data:
// Automatic fallback if base64 decryption fails
const decrypted = await SEA.decrypt(legacyEncrypted, key);
// Tries base64 first, then utf8
Use Cases
Decrypt Private User Data
gun.user().get('private').once(async (encrypted) => {
if (!encrypted) return;
const decrypted = await SEA.decrypt(encrypted, user._.sea);
console.log('Private data:', decrypted);
});
End-to-End Encrypted Messaging
// Bob receives message from Alice
gun.get('messages').get(msgId).once(async (data) => {
// Derive shared secret
const secret = await SEA.secret(alice.epub, bob);
// Decrypt message
const message = await SEA.decrypt(data.encrypted, secret);
console.log('Message from Alice:', message);
});
Decrypt Backup
const backupFile = await loadFile('backup.enc');
const password = prompt('Enter backup password:');
try {
const data = await SEA.decrypt(backupFile, password);
console.log('Backup restored:', data);
} catch (err) {
alert('Wrong password or corrupted backup');
}
Conditional Decryption
gun.get('data').on(async (data) => {
// Check if data is encrypted (starts with "SEA")
if (typeof data === 'string' && data.startsWith('SEA')) {
data = await SEA.decrypt(data, user._.sea);
}
displayData(data);
});
Security Considerations
Authentication Tag
AES-GCM includes authentication:
- Verifies data integrity
- Detects tampering
- Decryption fails if ciphertext modified
Reference: ~/workspace/source/sea/decrypt.js:22
{
name: 'AES-GCM',
iv: iv,
tagLength: 128 // 128-bit authentication tag
}
Key Security
Keep decryption keys secure:
- Never log keys to console
- Don’t send keys over unencrypted channels
- Store keys encrypted when possible
- Use the same key that was used for encryption
Timing Attacks
Web Crypto API implementations use constant-time operations to prevent timing attacks.
- Speed: Very fast (hardware-accelerated)
- Async: Always asynchronous
- Memory: Efficient (streaming decryption where supported)
const start = Date.now();
const decrypted = await SEA.decrypt(encrypted, key);
console.log('Decrypted in', Date.now() - start, 'ms');
Common Patterns
Decrypt Helper Function
const decryptIfNeeded = async (data, key) => {
if (typeof data === 'string' && data.startsWith('SEA')) {
return await SEA.decrypt(data, key);
}
return data; // Not encrypted
};
const result = await decryptIfNeeded(maybeEncrypted, key);
Batch Decryption
const encryptedItems = ['SEA{...}', 'SEA{...}', 'SEA{...}'];
const decrypted = await Promise.all(
encryptedItems.map(item => SEA.decrypt(item, key))
);
Safe Decryption
const safeDecrypt = async (encrypted, key, fallback = null) => {
try {
const result = await SEA.decrypt(encrypted, key);
return result || fallback;
} catch (err) {
console.error('Decryption error:', err);
return fallback;
}
};
const data = await safeDecrypt(encrypted, key, { default: true });
Integration with GUN
Auto-decrypt User Data
gun.user().get('secrets').on(async (encrypted) => {
if (!user.is) return; // Not authenticated
const decrypted = await SEA.decrypt(encrypted, user._.sea);
updateUI(decrypted);
});
Middleware Pattern
gun.get('private-data').on(async (data) => {
// Automatically decrypt all incoming data
if (data && typeof data === 'string' && data.startsWith('SEA')) {
data = await SEA.decrypt(data, user._.sea);
}
return data;
});
Troubleshooting
Decryption Returns Undefined
Causes:
- Wrong decryption key
- Corrupted encrypted data
- Data was not encrypted
- Different encoding used
Solution:
const result = await SEA.decrypt(data, key);
if (!result) {
// Try fallback or show error
console.error('Decryption failed');
}
“Could not decrypt” Error
Cause: Encoding mismatch or corrupted data
Solution:
try {
// Try with fallback encoding
return await SEA.decrypt(data, key, null, { encode: 'utf8' });
} catch (err) {
console.error('All decryption attempts failed');
}