@@ -26,6 +26,32 @@ var WRAP_ALGS = [
26
26
"ECDH-ES+A256KW"
27
27
] ;
28
28
29
+ var EC_OID = "1.2.840.10045.2.1" ;
30
+ function oidToCurveName ( oid ) {
31
+ switch ( oid ) {
32
+ case "1.2.840.10045.3.1.7" :
33
+ return "P-256" ;
34
+ case "1.3.132.0.34" :
35
+ return "P-384" ;
36
+ case "1.3.132.0.35" :
37
+ return "P-521" ;
38
+ default :
39
+ return null ;
40
+ }
41
+ }
42
+ function curveNameToOid ( crv ) {
43
+ switch ( crv ) {
44
+ case "P-256" :
45
+ return "1.2.840.10045.3.1.7" ;
46
+ case "P-384" :
47
+ return "1.3.132.0.34" ;
48
+ case "P-521" :
49
+ return "1.3.132.0.35" ;
50
+ default :
51
+ return null ;
52
+ }
53
+ }
54
+
29
55
var JWKEcCfg = {
30
56
publicKey : function ( props ) {
31
57
var fields = JWK . helpers . COMMON_PROPS . concat ( [
@@ -113,12 +139,62 @@ var JWKEcCfg = {
113
139
} ,
114
140
verifyKey : function ( alg , keys ) {
115
141
return keys . public ;
142
+ } ,
143
+
144
+ convertToPEM : function ( key , isPrivate ) {
145
+ // curveName to OID
146
+ var oid = key . crv ;
147
+ oid = curveNameToOid ( oid ) ;
148
+ oid = forge . asn1 . oidToDer ( oid ) ;
149
+ // key as bytes
150
+ var type ,
151
+ pub ,
152
+ asn1 ;
153
+ if ( isPrivate ) {
154
+ type = "EC PRIVATE KEY" ;
155
+ pub = Buffer . concat ( [
156
+ new Buffer ( [ 0x00 , 0x04 ] ) ,
157
+ key . x ,
158
+ key . y
159
+ ] ) . toString ( "binary" ) ;
160
+ key = key . d . toString ( "binary" ) ;
161
+ asn1 = forge . asn1 . create ( forge . asn1 . Class . UNIVERSAL , forge . asn1 . Type . SEQUENCE , true , [
162
+ forge . asn1 . create ( forge . asn1 . Class . UNIVERSAL , forge . asn1 . Type . INTEGER , false , "\u0001" ) ,
163
+ forge . asn1 . create ( forge . asn1 . Class . UNIVERSAL , forge . asn1 . Type . OCTETSTRING , false , key ) ,
164
+ forge . asn1 . create ( forge . asn1 . Class . CONTEXT_SPECIFIC , 0 , true , [
165
+ forge . asn1 . create ( forge . asn1 . Class . UNIVERSAL , forge . asn1 . Type . OID , false , oid . bytes ( ) )
166
+ ] ) ,
167
+ forge . asn1 . create ( forge . asn1 . Class . CONTEXT_SPECIFIC , 1 , true , [
168
+ forge . asn1 . create ( forge . asn1 . Class . UNIVERSAL , forge . asn1 . Type . BITSTRING , false , pub )
169
+ ] )
170
+ ] ) ;
171
+ } else {
172
+ type = "PUBLIC KEY" ;
173
+ key = Buffer . concat ( [
174
+ new Buffer ( [ 0x00 , 0x04 ] ) ,
175
+ key . x ,
176
+ key . y
177
+ ] ) . toString ( "binary" ) ;
178
+ asn1 = forge . asn1 . create ( forge . asn1 . Class . UNIVERSAL , forge . asn1 . Type . SEQUENCE , true , [
179
+ forge . asn1 . create ( forge . asn1 . Class . UNIVERSAL , forge . asn1 . Type . SEQUENCE , true , [
180
+ forge . asn1 . create ( forge . asn1 . Class . UNIVERSAL , forge . asn1 . Type . OID , false , forge . asn1 . oidToDer ( EC_OID ) . bytes ( ) ) ,
181
+ forge . asn1 . create ( forge . asn1 . Class . UNIVERSAL , forge . asn1 . Type . OID , false , oid . bytes ( ) )
182
+ ] ) ,
183
+ forge . asn1 . create ( forge . asn1 . Class . UNIVERSAL , forge . asn1 . Type . BITSTRING , false , key )
184
+ ] ) ;
185
+ }
186
+ asn1 = forge . asn1 . toDer ( asn1 ) . bytes ( ) ;
187
+ var pem = forge . pem . encode ( {
188
+ type : type ,
189
+ body : asn1
190
+ } ) ;
191
+ return pem ;
116
192
}
117
193
} ;
118
194
119
195
// Inspired by digitalbaazar/node-forge/js/rsa.js
120
196
var validators = {
121
- oid : "1.2.840.10045.2.1" ,
197
+ oid : EC_OID ,
122
198
privateKey : {
123
199
// ECPrivateKey
124
200
name : "ECPrivateKey" ,
@@ -215,19 +291,6 @@ var validators = {
215
291
}
216
292
} ;
217
293
218
- function oidToCurveName ( oid ) {
219
- switch ( oid ) {
220
- case "1.2.840.10045.3.1.7" :
221
- return "P-256" ;
222
- case "1.3.132.0.34" :
223
- return "P-384" ;
224
- case "1.3.132.0.35" :
225
- return "P-521" ;
226
- default :
227
- return null ;
228
- }
229
- }
230
-
231
294
var JWKEcFactory = {
232
295
kty : "EC" ,
233
296
validators : validators ,
0 commit comments