Skip to content

Commit 3065ac0

Browse files
committed
feat: Support sha256 and sha512 oaep algorithms
This is particularly useful because CloudFront's Field Level Encryption uses RSA_OAEP_SHA256_MGF1, which this library doesn't support yet. Support for oaepHash was added in node 12.9 (nodejs/node#28335), so this won't work for older node versions. It's still a backwards compatible change because by default `oaepHash` will be undefined, as before. I've updated the tests to cover use of the new parameter, but they're not very strict because they both encrypt and decrypt using the same parameter. This means if node silently ignores the oaepHash parameter (as it will in versions < 12.9) the tests will still pass, which isn't great. On the other hand, I think this project may still be being tested on an older version of node, so perhaps the fact the tests won't break is an unexpected blessing. I've also tested this manually against AWS CloudFront's Field Level Encryption and it seems to work. Resolves aws#198
1 parent 0a3107b commit 3065ac0

File tree

2 files changed

+12
-7
lines changed

2 files changed

+12
-7
lines changed

modules/raw-rsa-keyring-node/src/raw_rsa_keyring_node.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,9 @@ import {
3232
constants,
3333
publicEncrypt,
3434
privateDecrypt,
35-
randomBytes
35+
randomBytes,
36+
RsaPublicKey, // eslint-disable-line no-unused-vars
37+
RsaPrivateKey // eslint-disable-line no-unused-vars
3638
} from 'crypto'
3739

3840
import {
@@ -62,6 +64,7 @@ export type RawRsaKeyringNodeInput = {
6264
keyName: string
6365
rsaKey: RsaKey
6466
padding?: number
67+
oaepHash?: 'sha1'|'sha256'|'sha512'
6568
}
6669

6770
/* Node supports RSA_OAEP_SHA1_MFG1 by default.
@@ -78,7 +81,7 @@ export class RawRsaKeyringNode extends KeyringNode {
7881
constructor (input: RawRsaKeyringNodeInput) {
7982
super()
8083

81-
const { rsaKey, keyName, keyNamespace, padding = constants.RSA_PKCS1_OAEP_PADDING } = input
84+
const { rsaKey, keyName, keyNamespace, padding = constants.RSA_PKCS1_OAEP_PADDING, oaepHash } = input
8285
const { publicKey, privateKey } = rsaKey
8386
/* Precondition: RsaKeyringNode needs either a public or a private key to operate. */
8487
needs(publicKey || privateKey, 'No Key provided.')
@@ -90,7 +93,7 @@ export class RawRsaKeyringNode extends KeyringNode {
9093
if (!publicKey) throw new Error('No public key defined in constructor. Encrypt disabled.')
9194
const { buffer, byteOffset, byteLength } = unwrapDataKey(material.getUnencryptedDataKey())
9295
const encryptedDataKey = publicEncrypt(
93-
{ key: publicKey, padding },
96+
{ key: publicKey, padding, oaepHash } as RsaPublicKey,
9497
Buffer.from(buffer, byteOffset, byteLength))
9598
const providerInfo = this.keyName
9699
const providerId = this.keyNamespace
@@ -112,7 +115,7 @@ export class RawRsaKeyringNode extends KeyringNode {
112115
const { buffer, byteOffset, byteLength } = edk.encryptedDataKey
113116
const encryptedDataKey = Buffer.from(buffer, byteOffset, byteLength)
114117
const unencryptedDataKey = privateDecrypt(
115-
{ key: privateKey, padding },
118+
{ key: privateKey, padding, oaepHash } as RsaPrivateKey,
116119
encryptedDataKey)
117120
return material.setUnencryptedDataKey(unencryptedDataKey, trace)
118121
}

modules/raw-rsa-keyring-node/test/raw_rsa_keyring_node.test.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -126,13 +126,15 @@ describe('RawRsaKeyringNode::constructor', () => {
126126
})
127127
})
128128

129-
describe('RawRsaKeyringNode encrypt/decrypt', () => {
129+
const oaepHashOptions: (undefined|'sha1'|'sha256'|'sha512')[] = [undefined, 'sha1', 'sha256', 'sha512']
130+
oaepHashOptions.forEach(oaepHash => describe(`RawRsaKeyringNode encrypt/decrypt for oaepHash=${oaepHash || 'undefined'}`, () => {
130131
const keyNamespace = 'keyNamespace'
131132
const keyName = 'keyName'
132133
const keyring = new RawRsaKeyringNode({
133134
rsaKey: { privateKey: privatePem, publicKey: publicPem },
134135
keyName,
135-
keyNamespace
136+
keyNamespace,
137+
oaepHash
136138
})
137139
let encryptedDataKey: EncryptedDataKey
138140

@@ -179,4 +181,4 @@ describe('RawRsaKeyringNode encrypt/decrypt', () => {
179181
const material = new NodeDecryptionMaterial(suite, {})
180182
return expect(keyring._unwrapKey(material, encryptedDataKey)).to.rejectedWith(Error)
181183
})
182-
})
184+
}))

0 commit comments

Comments
 (0)