Skip to content

Commit 193c317

Browse files
author
John Bland
committed
add rsa sign/verify and public key export
add wc_RsaSSL_Sign and wc_RsaSSL_Verify bindings also add wc_RsaKeyToPublicDer so the public key can be exported, I thought the ToDer function did this
1 parent 40469eb commit 193c317

File tree

7 files changed

+233
-35
lines changed

7 files changed

+233
-35
lines changed

addon/wolfcrypt/h/rsa.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,18 @@
2222
#include <wolfssl/options.h>
2323
#include <wolfssl/wolfcrypt/settings.h>
2424
#include <wolfssl/wolfcrypt/rsa.h>
25+
#include <wolfssl/wolfcrypt/asn_public.h>
2526

2627
Napi::Number sizeof_RsaKey(const Napi::CallbackInfo& info);
2728
Napi::Number bind_wc_RsaEncryptSize(const Napi::CallbackInfo& info);
2829
Napi::Number bind_wc_InitRsaKey(const Napi::CallbackInfo& info);
2930
Napi::Number bind_wc_MakeRsaKey(const Napi::CallbackInfo& info);
3031
Napi::Number bind_wc_RsaKeyToDer(const Napi::CallbackInfo& info);
32+
Napi::Number bind_wc_RsaKeyToPublicDer(const Napi::CallbackInfo& info);
3133
Napi::Number bind_wc_RsaPrivateKeyDecode(const Napi::CallbackInfo& info);
3234
Napi::Number bind_wc_RsaPublicKeyDecode(const Napi::CallbackInfo& info);
3335
Napi::Number bind_wc_RsaPublicEncrypt(const Napi::CallbackInfo& info);
3436
Napi::Number bind_wc_RsaPrivateDecrypt(const Napi::CallbackInfo& info);
37+
Napi::Number bind_wc_RsaSSL_Sign(const Napi::CallbackInfo& info);
38+
Napi::Number bind_wc_RsaSSL_Verify(const Napi::CallbackInfo& info);
3539
Napi::Number bind_wc_FreeRsaKey(const Napi::CallbackInfo& info);

addon/wolfcrypt/main.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,10 +50,13 @@ Napi::Object Init(Napi::Env env, Napi::Object exports)
5050
exports.Set(Napi::String::New(env, "wc_InitRsaKey"), Napi::Function::New(env, bind_wc_InitRsaKey));
5151
exports.Set(Napi::String::New(env, "wc_MakeRsaKey"), Napi::Function::New(env, bind_wc_MakeRsaKey));
5252
exports.Set(Napi::String::New(env, "wc_RsaKeyToDer"), Napi::Function::New(env, bind_wc_RsaKeyToDer));
53+
exports.Set(Napi::String::New(env, "wc_RsaKeyToPublicDer"), Napi::Function::New(env, bind_wc_RsaKeyToPublicDer));
5354
exports.Set(Napi::String::New(env, "wc_RsaPrivateKeyDecode"), Napi::Function::New(env, bind_wc_RsaPrivateKeyDecode));
5455
exports.Set(Napi::String::New(env, "wc_RsaPublicKeyDecode"), Napi::Function::New(env, bind_wc_RsaPublicKeyDecode));
5556
exports.Set(Napi::String::New(env, "wc_RsaPublicEncrypt"), Napi::Function::New(env, bind_wc_RsaPublicEncrypt));
5657
exports.Set(Napi::String::New(env, "wc_RsaPrivateDecrypt"), Napi::Function::New(env, bind_wc_RsaPrivateDecrypt));
58+
exports.Set(Napi::String::New(env, "wc_RsaSSL_Sign"), Napi::Function::New(env, bind_wc_RsaSSL_Sign));
59+
exports.Set(Napi::String::New(env, "wc_RsaSSL_Verify"), Napi::Function::New(env, bind_wc_RsaSSL_Verify));
5760
exports.Set(Napi::String::New(env, "wc_FreeRsaKey"), Napi::Function::New(env, bind_wc_FreeRsaKey));
5861

5962
exports.Set(Napi::String::New(env, "Sha_digest_length"), Napi::Function::New(env, Sha_digest_length));

addon/wolfcrypt/rsa.cpp

Lines changed: 49 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,19 @@ Napi::Number bind_wc_RsaKeyToDer(const Napi::CallbackInfo& info)
7777
return Napi::Number::New( env, ret );
7878
}
7979

80+
Napi::Number bind_wc_RsaKeyToPublicDer(const Napi::CallbackInfo& info)
81+
{
82+
int ret;
83+
Napi::Env env = info.Env();
84+
RsaKey* rsa = (RsaKey*)( info[0].As<Napi::Uint8Array>().Data() );
85+
uint8_t* out = info[1].As<Napi::Uint8Array>().Data();
86+
int outSz = info[2].As<Napi::Number>().Int32Value();
87+
88+
ret = wc_RsaKeyToPublicDer( rsa, out, outSz );
89+
90+
return Napi::Number::New( env, ret );
91+
}
92+
8093
Napi::Number bind_wc_RsaPrivateKeyDecode(const Napi::CallbackInfo& info)
8194
{
8295
int ret;
@@ -110,12 +123,12 @@ Napi::Number bind_wc_RsaPublicEncrypt(const Napi::CallbackInfo& info)
110123
int ret;
111124
Napi::Env env = info.Env();
112125
uint8_t* in = info[0].As<Napi::Uint8Array>().Data();
113-
int inLen = info[1].As<Napi::Number>().Int32Value();
126+
int in_len = info[1].As<Napi::Number>().Int32Value();
114127
uint8_t* out = info[2].As<Napi::Uint8Array>().Data();
115-
int outLen = info[3].As<Napi::Number>().Int32Value();
128+
int out_len = info[3].As<Napi::Number>().Int32Value();
116129
RsaKey* rsa = (RsaKey*)( info[4].As<Napi::Uint8Array>().Data() );
117130

118-
ret = wc_RsaPublicEncrypt( in, inLen, out, outLen, rsa, rsa->rng );
131+
ret = wc_RsaPublicEncrypt( in, in_len, out, out_len, rsa, rsa->rng );
119132

120133
return Napi::Number::New( env, ret );
121134
}
@@ -125,12 +138,42 @@ Napi::Number bind_wc_RsaPrivateDecrypt(const Napi::CallbackInfo& info)
125138
int ret;
126139
Napi::Env env = info.Env();
127140
uint8_t* in = info[0].As<Napi::Uint8Array>().Data();
128-
int inLen = info[1].As<Napi::Number>().Int32Value();
141+
int in_len = info[1].As<Napi::Number>().Int32Value();
142+
uint8_t* out = info[2].As<Napi::Uint8Array>().Data();
143+
int out_len = info[3].As<Napi::Number>().Int32Value();
144+
RsaKey* rsa = (RsaKey*)( info[4].As<Napi::Uint8Array>().Data() );
145+
146+
ret = wc_RsaPrivateDecrypt( in, in_len, out, out_len, rsa );
147+
148+
return Napi::Number::New( env, ret );
149+
}
150+
151+
Napi::Number bind_wc_RsaSSL_Sign(const Napi::CallbackInfo& info)
152+
{
153+
int ret;
154+
Napi::Env env = info.Env();
155+
uint8_t* in = info[0].As<Napi::Uint8Array>().Data();
156+
int in_len = info[1].As<Napi::Number>().Int32Value();
157+
uint8_t* out = info[2].As<Napi::Uint8Array>().Data();
158+
int out_len = info[3].As<Napi::Number>().Int32Value();
159+
RsaKey* rsa = (RsaKey*)( info[4].As<Napi::Uint8Array>().Data() );
160+
161+
ret = wc_RsaSSL_Sign( in, in_len, out, out_len, rsa, rsa->rng );
162+
163+
return Napi::Number::New( env, ret );
164+
}
165+
166+
Napi::Number bind_wc_RsaSSL_Verify(const Napi::CallbackInfo& info)
167+
{
168+
int ret;
169+
Napi::Env env = info.Env();
170+
uint8_t* in = info[0].As<Napi::Uint8Array>().Data();
171+
int in_len = info[1].As<Napi::Number>().Int32Value();
129172
uint8_t* out = info[2].As<Napi::Uint8Array>().Data();
130-
int outLen = info[3].As<Napi::Number>().Int32Value();
173+
int out_len = info[3].As<Napi::Number>().Int32Value();
131174
RsaKey* rsa = (RsaKey*)( info[4].As<Napi::Uint8Array>().Data() );
132175

133-
ret = wc_RsaPrivateDecrypt( in, inLen, out, outLen, rsa );
176+
ret = wc_RsaSSL_Verify( in, in_len, out, out_len, rsa );
134177

135178
return Napi::Number::New( env, ret );
136179
}

app.js

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* hmac.h
1+
/* app.js
22
*
33
* Copyright (C) 2006-2022 wolfSSL Inc.
44
*
@@ -35,12 +35,10 @@ const ecc_tests = require( './tests/ecc' );
3535
await hmac_tests[key]()
3636
}
3737

38-
/*
3938
for ( const key of Object.keys( rsa_tests ) )
4039
{
4140
await rsa_tests[key]()
4241
}
43-
*/
4442

4543
for ( const key of Object.keys( sha_tests ) )
4644
{

interfaces/ecc.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ class WolfSSLEcc
5959
throw 'Ecc not allocated'
6060
}
6161

62+
// TODO is there a way to know this ahead of time to make sure our asnBuf is big enough
6263
let asnBuf = Buffer.alloc( 2048 )
6364

6465
let ret = wolfcrypt.wc_ecc_export_x963( this.ecc, asnBuf, asnBuf.length )

interfaces/rsa.js

Lines changed: 97 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -41,13 +41,14 @@ class WolfSSLRsa
4141
}
4242
}
4343

44-
RsaKeyToDer()
44+
KeyToDer()
4545
{
4646
if ( this.size == -1 || this.rsa == null )
4747
{
4848
throw 'Invalid rsa key'
4949
}
5050

51+
// TODO is there a way to know this ahead of time or shrink afterwards?
5152
let derBuf = Buffer.alloc( this.size )
5253

5354
let ret = wolfcrypt.wc_RsaKeyToDer( this.rsa, derBuf, this.size )
@@ -60,22 +61,49 @@ class WolfSSLRsa
6061
return derBuf
6162
}
6263

63-
RsaPrivateKeyDecode( derBuf )
64+
KeyToPublicDer()
65+
{
66+
if ( this.size == -1 || this.rsa == null )
67+
{
68+
throw 'Invalid rsa key'
69+
}
70+
71+
// TODO is there a way to know this ahead of time or shrink afterwards?
72+
let derBuf = Buffer.alloc( this.size )
73+
74+
let ret = wolfcrypt.wc_RsaKeyToPublicDer( this.rsa, derBuf, derBuf.length )
75+
76+
if ( ret < 0 )
77+
{
78+
throw `Failed to wc_RsaKeyToPublicDer ${ ret }`
79+
}
80+
81+
return derBuf
82+
}
83+
84+
PrivateKeyDecode( derBuf, size )
6485
{
6586
if ( this.rsa == null )
6687
{
6788
throw 'Invalid rsa key'
6889
}
6990

91+
if ( !Buffer.isBuffer( derBuf ) )
92+
{
93+
throw 'Private key der must be Buffer'
94+
}
95+
7096
let ret = wolfcrypt.wc_RsaPrivateKeyDecode( derBuf, this.rsa, derBuf.length )
7197

7298
if ( ret != 0 )
7399
{
74100
throw `Failed to wc_RsaPrivateKeyDecode ${ ret }`
75101
}
102+
103+
this.size = size
76104
}
77105

78-
RsaPublicKeyDecode( derBuf )
106+
PublicKeyDecode( derBuf, size )
79107
{
80108
if ( this.rsa == null )
81109
{
@@ -88,9 +116,11 @@ class WolfSSLRsa
88116
{
89117
throw `Failed to wc_RsaPublicKeyDecode ${ ret }`
90118
}
119+
120+
this.size = size
91121
}
92122

93-
RsaPublicEncrypt( data )
123+
PublicEncrypt( data )
94124
{
95125
if ( this.rsa == null )
96126
{
@@ -111,10 +141,12 @@ class WolfSSLRsa
111141
throw `Failed to wc_RsaPublicEncrypt ${ ret }`
112142
}
113143

144+
ciphertext = ciphertext.subarray( 0, ret )
145+
114146
return ciphertext
115147
}
116148

117-
RsaPrivateDecrypt( ciphertext )
149+
PrivateDecrypt( ciphertext )
118150
{
119151
if ( this.rsa == null )
120152
{
@@ -135,10 +167,68 @@ class WolfSSLRsa
135167
throw `Failed to wc_RsaPrivateDecrypt ${ ret }`
136168
}
137169

138-
return ciphertext
170+
data = data.subarray( 0, ret )
171+
172+
return data
173+
}
174+
175+
SSL_Sign( data )
176+
{
177+
if ( this.rsa == null )
178+
{
179+
throw 'Invalid rsa key'
180+
}
181+
182+
if ( typeof data == 'string' )
183+
{
184+
data = Buffer.from( data )
185+
}
186+
187+
let sig = Buffer.alloc( this.size / 8 )
188+
189+
let ret = wolfcrypt.wc_RsaSSL_Sign( data, data.length, sig, sig.length, this.rsa )
190+
191+
if ( ret <= 0 )
192+
{
193+
throw `Failed to wc_RsaSSL_Sign ${ ret }`
194+
}
195+
196+
return sig
197+
}
198+
199+
SSL_Verify( sig, data )
200+
{
201+
if ( this.rsa == null )
202+
{
203+
throw 'Invalid rsa key'
204+
}
205+
206+
if ( !Buffer.isBuffer( sig ) )
207+
{
208+
throw `signature must be a Buffer`
209+
}
210+
211+
if ( typeof data == 'string' )
212+
{
213+
data = Buffer.from( data )
214+
}
215+
216+
let validLength = wolfcrypt.wc_RsaSSL_Verify( sig, sig.length, data, data.length, this.rsa )
217+
218+
if ( validLength < 0 )
219+
{
220+
throw `Failed to wc_RsaSSL_Verify ${ validLength }`
221+
}
222+
223+
if ( validLength == data.length )
224+
{
225+
return true
226+
}
227+
228+
return false
139229
}
140230

141-
FreeRsaKey()
231+
free()
142232
{
143233
wolfcrypt.wc_FreeRsaKey( this.rsa )
144234
this.rsa = null

0 commit comments

Comments
 (0)