Skip to content

Commit 2c8aab0

Browse files
committed
feat: Add JWK Sign Support for NodeCrypto
1 parent bcc95a5 commit 2c8aab0

File tree

2 files changed

+38
-4
lines changed

2 files changed

+38
-4
lines changed

src/crypto/node/crypto.ts

+18-2
Original file line numberDiff line numberDiff line change
@@ -49,11 +49,27 @@ export class NodeCrypto implements Crypto {
4949
}
5050
}
5151

52-
async sign(privateKey: string, data: string | Buffer): Promise<string> {
52+
async sign(
53+
privateKey: string | JwkCertificate | crypto.JsonWebKey,
54+
data: string | Buffer
55+
): Promise<string> {
5356
const signer = crypto.createSign('RSA-SHA256');
5457
signer.update(data);
5558
signer.end();
56-
return signer.sign(privateKey, 'base64');
59+
60+
if (typeof privateKey === 'string') {
61+
// must be PEM
62+
return signer.sign(privateKey, 'base64');
63+
} else {
64+
// must be JWK
65+
return signer.sign(
66+
{
67+
key: privateKey as unknown as crypto.KeyObject,
68+
format: 'jwk',
69+
},
70+
'base64'
71+
);
72+
}
5773
}
5874

5975
decodeBase64StringUtf8(base64: string): string {

test/test.crypto.ts

+20-2
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,12 @@ import {
2121
fromArrayBufferToHex,
2222
} from '../src/crypto/crypto';
2323
import {NodeCrypto} from '../src/crypto/node/crypto';
24-
import {createPublicKey} from 'crypto';
24+
import {createPrivateKey, createPublicKey} from 'crypto';
2525

2626
const publicKey = fs.readFileSync('./test/fixtures/public.pem', 'utf-8');
2727
const privateKey = fs.readFileSync('./test/fixtures/private.pem', 'utf-8');
2828
const jwtPublicKeyJWT = createPublicKey(publicKey).export({format: 'jwk'});
29+
const jwtPrivateKeyJWT = createPrivateKey(privateKey).export({format: 'jwk'});
2930

3031
/**
3132
* Converts a Node.js Buffer to an ArrayBuffer.
@@ -100,7 +101,24 @@ describe('crypto', () => {
100101
assert(verified);
101102
});
102103

103-
it('should sign a message', async () => {
104+
it('should sign a message (JWT)', async () => {
105+
const message = 'This message is signed';
106+
const expectedSignatureBase64 = [
107+
'ufyKBV+Ar7Yq8CSmSIN9m38ch4xnWBz8CP4qHh6V+',
108+
'm4cCbeXdR1MEmWVhNJjZQFv3KL3tDAnl0Q4bTcSR/',
109+
'mmhXaRjdxyJ6xAUp0KcbVq6xsDIbnnYHSgYr3zVoS',
110+
'dRRefWSWTknN1S69fNmKEfUeBIJA93xitr3pbqtLC',
111+
'bP28XNU=',
112+
].join('');
113+
114+
const signatureBase64 = await crypto.sign(
115+
jwtPrivateKeyJWT as unknown as JwkCertificate,
116+
message
117+
);
118+
assert.strictEqual(signatureBase64, expectedSignatureBase64);
119+
});
120+
121+
it('should sign a message (PEM)', async () => {
104122
const message = 'This message is signed';
105123
const expectedSignatureBase64 = [
106124
'ufyKBV+Ar7Yq8CSmSIN9m38ch4xnWBz8CP4qHh6V+',

0 commit comments

Comments
 (0)