1
1
import jose from 'node-jose' ;
2
2
import b64u from 'base64url' ;
3
3
import any from 'promise.any' ;
4
+ import { pki } from 'node-forge' ;
4
5
5
6
import log from 'loglevel' ;
6
7
@@ -21,6 +22,31 @@ function paddedKey(key, alg, base64Secret) {
21
22
return b64u . encode ( buf ) ;
22
23
}
23
24
25
+ /*
26
+ * This function handles plain RSA keys not wrapped in a
27
+ * X.509 SubjectPublicKeyInfo structure. It returns a PEM encoded public key
28
+ * wrapper in that structure.
29
+ * See: https://stackoverflow.com/questions/18039401/how-can-i-transform-between-the-two-styles-of-public-key-format-one-begin-rsa
30
+ * @param {String } publicKey The public key as a PEM string.
31
+ * @returns {String } The PEM encoded public key in
32
+ * X509 SubjectPublicKeyInfo format.
33
+ */
34
+ function plainRsaKeyToX509Key ( key ) {
35
+ try {
36
+ const startTag = '-----BEGIN RSA PUBLIC KEY-----' ;
37
+ const endTag = '-----END RSA PUBLIC KEY-----' ;
38
+ const startTagPos = key . indexOf ( startTag ) ;
39
+ const endTagPos = key . indexOf ( endTag ) ;
40
+
41
+ return startTagPos !== - 1 && endTagPos !== - 1 ?
42
+ pki . publicKeyToPem ( pki . publicKeyFromPem ( key ) ) :
43
+ key ;
44
+ } catch ( e ) {
45
+ // If anything fails, it may not be a plain RSA key, so return the same key.
46
+ return key ;
47
+ }
48
+ }
49
+
24
50
function getJoseKey ( header , key , base64Secret ) {
25
51
if ( header . alg . indexOf ( 'HS' ) === 0 ) {
26
52
return jose . JWK . asKey ( {
@@ -30,6 +56,10 @@ function getJoseKey(header, key, base64Secret) {
30
56
k : paddedKey ( key , header . alg , base64Secret )
31
57
} ) ;
32
58
} else {
59
+ if ( header . alg . indexOf ( 'RS' ) === 0 ) {
60
+ key = plainRsaKeyToX509Key ( key ) ;
61
+ }
62
+
33
63
return any ( [ 'pem' , 'json' ] . map ( form => {
34
64
try {
35
65
return jose . JWK . asKey ( key , form ) ;
@@ -65,45 +95,6 @@ export function sign(header,
65
95
) ;
66
96
}
67
97
68
- // TODO: reenable this (and tests)
69
- /**
70
- * This function takes a PEM string with a public key and returns a
71
- * jsrsasign key object (RSAKey, KJUR.crypto.DSA, KJUR.crypto.ECDSA). It also
72
- * handles plain RSA keys not wrapped in a X.509 SubjectPublicKeyInfo
73
- * structure.
74
- * See: https://stackoverflow.com/questions/18039401/how-can-i-transform-between-the-two-styles-of-public-key-format-one-begin-rsa
75
- * @param {String } publicKey The public key as a PEM string.
76
- * @returns {Object } The public key as a jsrsasign key object.
77
- * /
78
- function getPublicKeyObject(publicKey) {
79
- try {
80
- const startTag = '-----BEGIN RSA PUBLIC KEY-----';
81
- const endTag = '-----END RSA PUBLIC KEY-----';
82
- const startTagPos = publicKey.indexOf(startTag);
83
- const endTagPos = publicKey.indexOf(endTag);
84
-
85
- if(startTagPos !== -1 && endTagPos !== -1) {
86
- const plainDataBase64 =
87
- publicKey.substr(0, endTagPos)
88
- .substr(startTagPos + startTag.length);
89
-
90
- const plainDataDER = b64tohex(plainDataBase64);
91
-
92
- const barePublicKey = {
93
- n: ASN1HEX.getVbyList(plainDataDER, 0, [0], '02'),
94
- e: ASN1HEX.getVbyList(plainDataDER, 0, [1], '02')
95
- };
96
-
97
- return KEYUTIL.getKey(barePublicKey);
98
- }
99
- } catch(e) {
100
- log.error('Failed to make public key into X.509 ' +
101
- 'SubjectPublicKeyInfo key:', e);
102
- }
103
-
104
- return KEYUTIL.getKey(publicKey);
105
- }*/
106
-
107
98
export function verify ( jwt , secretOrPublicKeyString , base64Secret = false ) {
108
99
if ( ! isToken ( jwt ) ) {
109
100
return Promise . resolve ( false ) ;
0 commit comments