Skip to content

Commit 9d3faf4

Browse files
committed
crypto: add support for RSA public key signing/verification
1 parent 3ac5f11 commit 9d3faf4

File tree

4 files changed

+62
-3
lines changed

4 files changed

+62
-3
lines changed

src/node_crypto.cc

+19-3
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,11 @@
5454
return ThrowException(Exception::TypeError(String::New("Not a string or buffer"))); \
5555
}
5656

57-
static const char *PUBLIC_KEY_PFX = "-----BEGIN PUBLIC KEY-----";
58-
static const int PUBLIC_KEY_PFX_LEN = strlen(PUBLIC_KEY_PFX);
57+
static const char PUBLIC_KEY_PFX[] = "-----BEGIN PUBLIC KEY-----";
58+
static const int PUBLIC_KEY_PFX_LEN = sizeof(PUBLIC_KEY_PFX) - 1;
59+
60+
static const char PUBRSA_KEY_PFX[] = "-----BEGIN RSA PUBLIC KEY-----";
61+
static const int PUBRSA_KEY_PFX_LEN = sizeof(PUBRSA_KEY_PFX) - 1;
5962

6063
static const int X509_NAME_FLAGS = ASN1_STRFLGS_ESC_CTRL
6164
| ASN1_STRFLGS_ESC_MSB
@@ -3304,13 +3307,26 @@ class Verify : public ObjectWrap {
33043307
return 0;
33053308
}
33063309

3307-
// Check if this is a PKCS#8 public key before trying as X.509
3310+
// Check if this is a PKCS#8 or RSA public key before trying as X.509.
3311+
// Split this out into a separate function once we have more than one
3312+
// consumer of public keys.
33083313
if (strncmp(key_pem, PUBLIC_KEY_PFX, PUBLIC_KEY_PFX_LEN) == 0) {
33093314
pkey = PEM_read_bio_PUBKEY(bp, NULL, NULL, NULL);
33103315
if (pkey == NULL) {
33113316
ERR_print_errors_fp(stderr);
33123317
return 0;
33133318
}
3319+
} else if (strncmp(key_pem, PUBRSA_KEY_PFX, PUBRSA_KEY_PFX_LEN) == 0) {
3320+
RSA* rsa = PEM_read_bio_RSAPublicKey(bp, NULL, NULL, NULL);
3321+
if (rsa) {
3322+
pkey = EVP_PKEY_new();
3323+
if (pkey) EVP_PKEY_set1_RSA(pkey, rsa);
3324+
RSA_free(rsa);
3325+
}
3326+
if (pkey == NULL) {
3327+
ERR_print_errors_fp(stderr);
3328+
return 0;
3329+
}
33143330
} else {
33153331
// X.509 fallback
33163332
x509 = PEM_read_bio_X509(bp, NULL, NULL, NULL);

test/fixtures/test_rsa_privkey_2.pem

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
-----BEGIN RSA PRIVATE KEY-----
2+
MIICWQIBAAKBgQCsMgRdxxEeeXscPvqFzp/6/IIdoeKSlBn7361FWZwMQUG0qCbr
3+
XYtdXPyqp2B4GThviIqiaJZITCTY87CiV7bFvH2lmUMJLsCc3BaQ4XFQbEU5D5jN
4+
FfP7g78MEKbCb9rEfYMI2EGwbfKRUZUrYeBadzIMHEMEHDyiBXrCohTXMQIBIwKB
5+
gHEoLsFITRQGr/yeah1qhmMa9ms+fvKb1o+S/NXNLAgNoDTjh0o2KGHspgm+cpgQ
6+
kszzU8nPszbS86SC4cnEnKy/g3uw3Lf55a2P8vgh1P386/PzI+Im8s6E/EpDwn/P
7+
R2E5gqTfePl8m7r9oeIARZXysmHHgBtEm5pTUav6QvOLAkEA2arx2R/3Yb6yZ5oO
8+
3ldZEzCBNmB6mCoczrH6jjBosb4Gj7TK+asNlbinw1gj8sgdkzAw6jGnJ2IUfftm
9+
QMykwQJBAMqFDclCf2b9cwi82+Xg+mjlT8BEf+l5xdRrweOyjB6DmUhgeqDISJUK
10+
JgxGr4TxIQ6DGeEWxChGzzU6utlRnnECQDf4wdi/E7oMdwSylhvqkz9y32XBCZTX
11+
oQHzQG20rTUE+l93oeht0EsSOcSEYQPqUL9yyr/g4dbtVbn+0SabBcsCQEs4u/pL
12+
5i2RVpzYbu77yrk/OuEDf/eiQipT6O4sX+4Tn1VlqePynp3B8N/8/11DnpBclJVu
13+
2yTnGcNQVAeTWBsCQFMekiY/KbwAgTopqpCUg5CLNph91FVW5PIntLmd5gSj8ZJS
14+
uNuro8CURrOe8iiI3pG9m4KkbDdOBSOMADXJojE=
15+
-----END RSA PRIVATE KEY-----

test/fixtures/test_rsa_pubkey_2.pem

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
-----BEGIN RSA PUBLIC KEY-----
2+
MIGHAoGBAKwyBF3HER55exw++oXOn/r8gh2h4pKUGfvfrUVZnAxBQbSoJutdi11c
3+
/KqnYHgZOG+IiqJolkhMJNjzsKJXtsW8faWZQwkuwJzcFpDhcVBsRTkPmM0V8/uD
4+
vwwQpsJv2sR9gwjYQbBt8pFRlSth4Fp3MgwcQwQcPKIFesKiFNcxAgEj
5+
-----END RSA PUBLIC KEY-----

test/simple/test-crypto.js

+23
Original file line numberDiff line numberDiff line change
@@ -394,6 +394,29 @@ assert.equal(rsaSignature, '5c50e3145c4e2497aadb0eabc83b342d0b0021ece0d4c4a064b7
394394
rsaVerify.update(rsaPubPem);
395395
assert.strictEqual(rsaVerify.verify(rsaPubPem, rsaSignature, 'hex'), true);
396396

397+
(function() {
398+
var privateKey = fs.readFileSync(
399+
common.fixturesDir + '/test_rsa_privkey_2.pem');
400+
401+
var publicKey = fs.readFileSync(
402+
common.fixturesDir + '/test_rsa_pubkey_2.pem');
403+
404+
var input = 'I AM THE WALRUS';
405+
406+
var signature = '79d59d34f56d0e94aa6a3e306882b52ed4191f07521f25f505a078dc2f89396e0c8ac89e996fde5717f4cb89199d8fec249961fcb07b74cd3d2a4ffa235417b69618e4bcd76b97e29975b7ce862299410e1b522a328e44ac9bb28195e0268da7eda23d9825ac43c724e86ceeee0d0d4465678652ccaf65010ddfb299bedeb1ad';
407+
408+
var sign = crypto.createSign('RSA-SHA256');
409+
sign.update(input);
410+
411+
var output = sign.sign(privateKey, 'hex');
412+
assert.equal(output, signature);
413+
414+
var verify = crypto.createVerify('RSA-SHA256');
415+
verify.update(input);
416+
417+
assert.strictEqual(verify.verify(publicKey, signature, 'hex'), true);
418+
})();
419+
397420
// Test PBKDF2 with RFC 6070 test vectors (except #4)
398421

399422
crypto.pbkdf2('password', 'salt', 1, 20, function(err, result) {

0 commit comments

Comments
 (0)