Skip to content

Commit ad7e5e3

Browse files
authored
Merge pull request #395 from bsv-blockchain/feature/decrypt-validation
Feature/decrypt validation
2 parents 73b6ae6 + a34b4c4 commit ad7e5e3

File tree

5 files changed

+50
-12
lines changed

5 files changed

+50
-12
lines changed

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ All notable changes to this project will be documented in this file. The format
55
## Table of Contents
66

77
- [Unreleased](#unreleased)
8+
- [1.9.12 - 2025-12-01](#1912---2025-12-01)
89
- [1.9.11 - 2025-11-24](#1911---2025-11-24)
910
- [1.9.10 - 2025-11-17](#1910---2025-11-17)
1011
- [1.9.9 - 2025-11-15](#199---2025-11-15)
@@ -182,6 +183,13 @@ All notable changes to this project will be documented in this file. The format
182183

183184
### Security
184185

186+
---
187+
### [1.9.12] - 2025-12-01
188+
189+
### Added
190+
191+
- Added decryption validation to SymmetricKey.
192+
185193
---
186194
### [1.9.11] - 2025-11-24
187195

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@bsv/sdk",
3-
"version": "1.9.11",
3+
"version": "1.9.12",
44
"type": "module",
55
"description": "BSV Blockchain Software Development Kit",
66
"main": "dist/cjs/mod.js",

src/primitives/SymmetricKey.ts

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -44,12 +44,7 @@ export default class SymmetricKey extends BigNumber {
4444
const iv = Random(32)
4545
msg = toArray(msg, enc)
4646
const keyBytes = this.toArray('be', 32)
47-
const { result, authenticationTag } = AESGCM(
48-
msg,
49-
[],
50-
iv,
51-
keyBytes
52-
)
47+
const { result, authenticationTag } = AESGCM(msg, [], iv, keyBytes)
5348
const totalLength = iv.length + result.length + authenticationTag.length
5449
const combined = new Array(totalLength)
5550
let offset = 0
@@ -79,10 +74,23 @@ export default class SymmetricKey extends BigNumber {
7974
*/
8075
decrypt (msg: number[] | string, enc?: 'hex' | 'utf8'): string | number[] {
8176
msg = toArray(msg, enc)
82-
const iv = msg.slice(0, 32)
83-
const tagStart = msg.length - 16
84-
const ciphertext = msg.slice(32, tagStart)
77+
78+
const ivLength = 32
79+
const tagLength = 16
80+
81+
if (msg.length < ivLength + tagLength) {
82+
throw new Error('Ciphertext too short')
83+
}
84+
85+
const iv = msg.slice(0, ivLength)
86+
const tagStart = msg.length - tagLength
87+
const ciphertext = msg.slice(ivLength, tagStart)
8588
const messageTag = msg.slice(tagStart)
89+
90+
if (tagStart < ivLength) {
91+
throw new Error('Malformed ciphertext')
92+
}
93+
8694
const result = AESGCMDecrypt(
8795
ciphertext,
8896
[],

src/primitives/__tests/SymmetricKey.test.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,5 +102,27 @@ describe('SymmetricKey', () => {
102102

103103
expect(decrypted).toBe(plaintext)
104104
})
105+
106+
it('throws "Ciphertext too short" for inputs shorter than IV + tag', () => {
107+
const shortCipherArray = new Array(47).fill(0)
108+
expect(() => {
109+
KEYS[0].decrypt(shortCipherArray)
110+
}).toThrow(new Error('Ciphertext too short'))
111+
})
112+
113+
it('throws "Ciphertext too short" for hex-encoded inputs shorter than IV + tag', () => {
114+
const shortBuffer = Buffer.alloc(47, 0)
115+
const shortHex = shortBuffer.toString('hex')
116+
117+
expect(() => {
118+
KEYS[0].decrypt(shortHex, 'hex')
119+
}).toThrow(new Error('Ciphertext too short'))
120+
})
121+
122+
it('still throws "Decryption failed!" for structurally valid but wrong ciphertext', () => {
123+
expect(() => {
124+
KEYS[2].decrypt(CIPHERTEXT_1, 'hex')
125+
}).toThrow(new Error('Decryption failed!'))
126+
})
105127
})
106128
})

0 commit comments

Comments
 (0)