@@ -18,47 +18,78 @@ describe('aes128', () => {
1818 return Buffer . concat ( [ data , paddingBuffer ] ) ;
1919 } ;
2020
21- // PKCS#7 padding removal
22- const removePadding = ( paddedBuffer : Buffer ) : Buffer => {
23- // We get padding length from the last byte - in PKCS#7 all the padded bytes contain padding length
24- // and there is always some padding.
25- const paddingToRemove = paddedBuffer [ paddedBuffer . length - 1 ] ;
26- return paddedBuffer . subarray ( 0 , paddedBuffer . length - paddingToRemove ) ;
21+ // Encrypt data with Node's built-in AES-128-CBC
22+ const encrypt = ( data : Buffer , key : Buffer , iv : Buffer ) : Buffer => {
23+ const cipher = createCipheriv ( 'aes-128-cbc' , key , iv ) ;
24+ cipher . setAutoPadding ( false ) ;
25+ return Buffer . concat ( [ cipher . update ( pad ( data ) ) , cipher . final ( ) ] ) ;
2726 } ;
2827
2928 it ( 'should correctly encrypt input' , async ( ) => {
3029 const data = randomBytes ( 32 ) ;
3130 const key = randomBytes ( 16 ) ;
3231 const iv = randomBytes ( 16 ) ;
3332
34- const paddedData = pad ( data ) ;
35-
36- const cipher = createCipheriv ( 'aes-128-cbc' , key , iv ) ;
37- cipher . setAutoPadding ( false ) ;
38- const expected = Buffer . concat ( [ cipher . update ( paddedData ) , cipher . final ( ) ] ) ;
39-
4033 const result : Buffer = await aes128 . encryptBufferCBC ( data , iv , key ) ;
4134
42- expect ( result ) . toEqual ( expected ) ;
35+ expect ( result ) . toEqual ( encrypt ( data , key , iv ) ) ;
4336 } ) ;
4437
4538 it ( 'should correctly decrypt input' , async ( ) => {
4639 const data = randomBytes ( 32 ) ;
4740 const key = randomBytes ( 16 ) ;
4841 const iv = randomBytes ( 16 ) ;
4942
50- const paddedData = pad ( data ) ;
51-
52- const cipher = createCipheriv ( 'aes-128-cbc' , key , iv ) ;
53- cipher . setAutoPadding ( false ) ;
54- const ciphertext = Buffer . concat ( [ cipher . update ( paddedData ) , cipher . final ( ) ] ) ;
43+ const ciphertext = encrypt ( data , key , iv ) ;
5544
5645 const decipher = createDecipheriv ( 'aes-128-cbc' , key , iv ) ;
5746 decipher . setAutoPadding ( false ) ;
58- const expected = removePadding ( Buffer . concat ( [ decipher . update ( ciphertext ) , decipher . final ( ) ] ) ) ;
47+ const decrypted = Buffer . concat ( [ decipher . update ( ciphertext ) , decipher . final ( ) ] ) ;
48+ const expected = decrypted . subarray ( 0 , decrypted . length - decrypted [ decrypted . length - 1 ] ) ;
5949
6050 const result : Buffer = await aes128 . decryptBufferCBC ( ciphertext , iv , key ) ;
6151
6252 expect ( result ) . toEqual ( expected ) ;
6353 } ) ;
54+
55+ it ( 'should throw on invalid PKCS#7 padding length (0)' , async ( ) => {
56+ const key = randomBytes ( 16 ) ;
57+ const iv = randomBytes ( 16 ) ;
58+ // Craft a ciphertext whose last plaintext byte decrypts to 0x00 (invalid padding length).
59+ // We encrypt a block where the last byte is 0x00 using raw (no-padding) encryption.
60+ const plaintext = Buffer . alloc ( 16 , 0x00 ) ;
61+ const cipher = createCipheriv ( 'aes-128-cbc' , key , iv ) ;
62+ cipher . setAutoPadding ( false ) ;
63+ const ciphertext = Buffer . concat ( [ cipher . update ( plaintext ) , cipher . final ( ) ] ) ;
64+
65+ await expect ( aes128 . decryptBufferCBC ( ciphertext , iv , key ) ) . rejects . toThrow ( 'Invalid PKCS#7 padding length: 0' ) ;
66+ } ) ;
67+
68+ it ( 'should throw on invalid PKCS#7 padding length (> 16)' , async ( ) => {
69+ const key = randomBytes ( 16 ) ;
70+ const iv = randomBytes ( 16 ) ;
71+ // Craft a ciphertext whose last plaintext byte is 0x11 = 17, which exceeds the block size.
72+ const plaintext = Buffer . alloc ( 16 , 0x11 ) ;
73+ const cipher = createCipheriv ( 'aes-128-cbc' , key , iv ) ;
74+ cipher . setAutoPadding ( false ) ;
75+ const ciphertext = Buffer . concat ( [ cipher . update ( plaintext ) , cipher . final ( ) ] ) ;
76+
77+ await expect ( aes128 . decryptBufferCBC ( ciphertext , iv , key ) ) . rejects . toThrow ( 'Invalid PKCS#7 padding length: 17' ) ;
78+ } ) ;
79+
80+ it ( 'should throw when padding bytes are inconsistent' , async ( ) => {
81+ const key = randomBytes ( 16 ) ;
82+ const iv = randomBytes ( 16 ) ;
83+ // Last byte says padding length is 4, but the 3 bytes before it are not 0x04.
84+ const plaintext = Buffer . alloc ( 16 , 0x00 ) ;
85+ plaintext [ 15 ] = 0x04 ;
86+ plaintext [ 14 ] = 0x04 ;
87+ plaintext [ 13 ] = 0x04 ;
88+ plaintext [ 12 ] = 0x01 ; // should be 0x04 — inconsistent
89+ const cipher = createCipheriv ( 'aes-128-cbc' , key , iv ) ;
90+ cipher . setAutoPadding ( false ) ;
91+ const ciphertext = Buffer . concat ( [ cipher . update ( plaintext ) , cipher . final ( ) ] ) ;
92+
93+ await expect ( aes128 . decryptBufferCBC ( ciphertext , iv , key ) ) . rejects . toThrow ( 'Invalid PKCS#7 padding' ) ;
94+ } ) ;
6495} ) ;
0 commit comments