fix:
Added DisposedError Wrapped zeroMemory() in its own try/catch in finally Generic error message; fixed ArrayBufferLike TypeScript type issue Generic error message; password/salt/IV wrapped in SecureByteContext Password ≥8 chars enforced; zeroKeys(); rotateKeys(); debug-gated logs; TS type fix Zero source ArrayBuffer after req.write() Added timeout, debug, keyRotationInterval, keyRotationDir, keyRotationPassword dispose(), assertNotDisposed(), startKeyRotationTimer(), rotateKeys(); Promise-mutex on ensureKeys(); new URL() validation; CR/LF API key check; server error detail truncation; response schema validation; all console.log behind debugMode Propagates new config fields; dispose() Tests for dispose, timer, header injection, URL validation, error sanitization, debug flag Tests for generic error messages, password validation, zeroKeys()
This commit is contained in:
parent
76703e2e3e
commit
d9d2ec98db
11 changed files with 582 additions and 129 deletions
|
|
@ -40,6 +40,20 @@ describe('AESEncryption', () => {
|
|||
await expect(aes.decrypt(ciphertext, nonce, key2)).rejects.toThrow();
|
||||
});
|
||||
|
||||
test('decrypt with wrong key throws generic message (no internal details)', async () => {
|
||||
const key1 = await aes.generateKey();
|
||||
const key2 = await aes.generateKey();
|
||||
const { ciphertext, nonce } = await aes.encrypt(stringToArrayBuffer('secret'), key1);
|
||||
|
||||
await expect(aes.decrypt(ciphertext, nonce, key2))
|
||||
.rejects.toThrow('AES-GCM decryption failed');
|
||||
try {
|
||||
await aes.decrypt(ciphertext, nonce, key2);
|
||||
} catch (e) {
|
||||
expect((e as Error).message).toBe('AES-GCM decryption failed');
|
||||
}
|
||||
});
|
||||
|
||||
test('exportKey / importKey roundtrip', async () => {
|
||||
const key = await aes.generateKey();
|
||||
const exported = await aes.exportKey(key);
|
||||
|
|
@ -124,6 +138,64 @@ describe('RSAOperations', () => {
|
|||
const pem = await rsa.exportPrivateKey(kp.privateKey, 'correct-password');
|
||||
await expect(rsa.importPrivateKey(pem, 'wrong-password')).rejects.toThrow();
|
||||
}, 30000);
|
||||
|
||||
test('decryptKey with wrong private key throws generic message', async () => {
|
||||
const kp1 = await rsa.generateKeyPair(2048);
|
||||
const kp2 = await rsa.generateKeyPair(2048);
|
||||
const aes = new AESEncryption();
|
||||
const aesKey = await aes.generateKey();
|
||||
const aesKeyBytes = await aes.exportKey(aesKey);
|
||||
|
||||
const encrypted = await rsa.encryptKey(aesKeyBytes, kp1.publicKey);
|
||||
|
||||
await expect(rsa.decryptKey(encrypted, kp2.privateKey))
|
||||
.rejects.toThrow('RSA key decryption failed');
|
||||
try {
|
||||
await rsa.decryptKey(encrypted, kp2.privateKey);
|
||||
} catch (e) {
|
||||
// Must not contain internal engine error details
|
||||
expect((e as Error).message).toBe('RSA key decryption failed');
|
||||
}
|
||||
}, 30000);
|
||||
});
|
||||
|
||||
describe('KeyManager password validation', () => {
|
||||
test('generateKeys rejects password shorter than 8 characters', async () => {
|
||||
const { KeyManager } = await import('../../src/core/crypto/keys');
|
||||
const km = new KeyManager();
|
||||
await expect(km.generateKeys({ keySize: 2048, password: 'short' }))
|
||||
.rejects.toThrow('at least 8 characters');
|
||||
}, 30000);
|
||||
|
||||
test('generateKeys rejects empty password', async () => {
|
||||
const { KeyManager } = await import('../../src/core/crypto/keys');
|
||||
const km = new KeyManager();
|
||||
await expect(km.generateKeys({ keySize: 2048, password: '' }))
|
||||
.rejects.toThrow('at least 8 characters');
|
||||
}, 30000);
|
||||
|
||||
test('generateKeys accepts password of exactly 8 characters', async () => {
|
||||
const { KeyManager } = await import('../../src/core/crypto/keys');
|
||||
const km = new KeyManager();
|
||||
await expect(km.generateKeys({ keySize: 2048, password: '12345678' }))
|
||||
.resolves.toBeUndefined();
|
||||
}, 30000);
|
||||
|
||||
test('generateKeys accepts undefined password (no encryption)', async () => {
|
||||
const { KeyManager } = await import('../../src/core/crypto/keys');
|
||||
const km = new KeyManager();
|
||||
await expect(km.generateKeys({ keySize: 2048 }))
|
||||
.resolves.toBeUndefined();
|
||||
}, 30000);
|
||||
|
||||
test('zeroKeys clears key references', async () => {
|
||||
const { KeyManager } = await import('../../src/core/crypto/keys');
|
||||
const km = new KeyManager();
|
||||
await km.generateKeys({ keySize: 2048 });
|
||||
expect(km.hasKeys()).toBe(true);
|
||||
km.zeroKeys();
|
||||
expect(km.hasKeys()).toBe(false);
|
||||
}, 30000);
|
||||
});
|
||||
|
||||
describe('Base64 utilities', () => {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue