Skip to content

Commit

Permalink
Add publicEncrypt().
Browse files Browse the repository at this point in the history
Not yet fully tested.
  • Loading branch information
Dan Bornstein committed Feb 9, 2012
1 parent 7eb6cca commit 7997222
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 12 deletions.
63 changes: 56 additions & 7 deletions src/ursaNative.cc
Expand Up @@ -176,11 +176,11 @@ static bool isBuffer(const Arguments& args, int index) {
}

/**
* Get a Buffer out of the args[0], converted to a freshly-allocated
* Get a Buffer out of args[0], converted to a freshly-allocated
* memory BIO. Returns a non-null pointer on success. On failure,
* schedules an exception and returns NULL.
*/
static BIO *getArg0Buffer(const Arguments& args) {
static BIO *getArg0Bio(const Arguments& args) {
if (!isBuffer(args, 0)) { return NULL; }

Local<Object> buf = args[0]->ToObject();
Expand All @@ -193,6 +193,20 @@ static BIO *getArg0Buffer(const Arguments& args) {
return bio;
}

/**
* Get a Buffer out of args[0], yielding a data pointer and length.
* Returns a non-null pointer on success and sets the given length
* pointer. On failure, schedules an exception and returns NULL.
*/
static void *getArg0DataAndLength(const Arguments& args, int *lengthPtr) {
if (!isBuffer(args, 0)) { return NULL; }

Local<Object> buf = args[0]->ToObject();

*lengthPtr = node::Buffer::Length(buf);
return node::Buffer::Data(buf);
}

/**
* Get a Buffer out of args[1], converted to a freshly-allocated (char
* *). Returns a non-null pointer on success. On failure, schedules an
Expand Down Expand Up @@ -403,6 +417,10 @@ Handle<Value> RsaWrap::PrivateDecrypt(const Arguments& args) {
RsaWrap *obj = unwrapExpectPrivateKey(args);
if (obj == NULL) { return Undefined(); }

int length;
void *data = getArg0DataAndLength(args, &length);
if (data == NULL) { return Undefined(); }

// FIXME: Need real implementation.
return scope.Close(String::New("world"));
}
Expand All @@ -414,6 +432,10 @@ Handle<Value> RsaWrap::PrivateEncrypt(const Arguments& args) {
RsaWrap *obj = unwrapExpectPrivateKey(args);
if (obj == NULL) { return Undefined(); }

int length;
void *data = getArg0DataAndLength(args, &length);
if (data == NULL) { return Undefined(); }

// FIXME: Need real implementation.
return scope.Close(String::New("world"));
}
Expand All @@ -425,19 +447,46 @@ Handle<Value> RsaWrap::PublicDecrypt(const Arguments& args) {
RsaWrap *obj = unwrapExpectSet(args);
if (obj == NULL) { return Undefined(); }

int length;
void *data = getArg0DataAndLength(args, &length);
if (data == NULL) { return Undefined(); }

// FIXME: Need real implementation.
return scope.Close(String::New("world"));
}

// FIXME: Need documentation.
/**
* Perform encryption on the given buffer using the public (aspect of the)
* RSA key. This always uses the padding mode RSA_PKCS1_OAEP_PADDING.
*/
Handle<Value> RsaWrap::PublicEncrypt(const Arguments& args) {
HandleScope scope;

RsaWrap *obj = unwrapExpectSet(args);
if (obj == NULL) { return Undefined(); }

// FIXME: Need real implementation.
return scope.Close(String::New("world"));
int length;
void *data = getArg0DataAndLength(args, &length);
if (data == NULL) { return Undefined(); }

int rsaLength = RSA_size(obj->rsa);
node::Buffer *result = node::Buffer::New(rsaLength);

if (result == NULL) {
scheduleAllocException();
return Undefined();
}

int ret = RSA_public_encrypt(length, (unsigned char *) data,
(unsigned char *) node::Buffer::Data(result),
obj->rsa, RSA_PKCS1_OAEP_PADDING);

if (ret < 0) {
scheduleSslException();
return Undefined();
}

return result->handle_;
}

/**
Expand All @@ -454,7 +503,7 @@ Handle<Value> RsaWrap::SetPrivateKeyPem(const Arguments& args) {

BIO *bio = NULL;
if (ok) {
bio = getArg0Buffer(args);
bio = getArg0Bio(args);
ok &= (bio != NULL);
}

Expand Down Expand Up @@ -485,7 +534,7 @@ Handle<Value> RsaWrap::SetPublicKeyPem(const Arguments& args) {
RsaWrap *obj = unwrapExpectUnset(args);
if (obj == NULL) { return Undefined(); }

BIO *bio = getArg0Buffer(args);
BIO *bio = getArg0Bio(args);
if (bio == NULL) { return Undefined(); }

obj->rsa = PEM_read_bio_RSA_PUBKEY(bio, NULL, NULL, NULL);
Expand Down
18 changes: 13 additions & 5 deletions test/native.js
Expand Up @@ -225,17 +225,20 @@ function test_fail_privateDecrypt() {
}

function test_publicEncrypt() {
// No other reasonable way to test this than to do a round trip.
var plainBuf = new Buffer(fixture.PLAINTEXT, fixture.UTF8);

var rsa = new RsaWrap();
rsa.setPublicKeyPem(fixture.PUBLIC_KEY);
var encoded = rsa.publicEncrypt(encoded).toString(fixture.Hex);
assert.equal(encoded, fixture.PRIVATE_CIPHERTEXT_HEX);
var encoded = rsa.publicEncrypt(plainBuf);
var decoded = rsa.privateDecrypt(encoded).toString(fixture.UTF8);
assert.equal(decoded, fixture.PLAINTEXT);

rsa = new RsaWrap();
rsa.setPrivateKeyPem(fixture.PRIVATE_KEY);
encoded = rsa.publicEncrypt(encoded).toString(fixture.Hex);
assert.equal(encoded, fixture.PRIVATE_CIPHERTEXT_HEX);
encoded = rsa.publicEncrypt(plainBuf);
decoded = rsa.privateDecrypt(encoded).toString(fixture.UTF8);
assert.equal(decoded, fixture.PLAINTEXT);
}

function test_fail_publicEncrypt() {
Expand All @@ -253,7 +256,12 @@ function test_fail_publicEncrypt() {
function f2() {
rsa.publicEncrypt("x");
}
assert.throws(f2, /arg mumble FIXME/);
assert.throws(f2, /Expected a Buffer in args\[0]\./);

function f3() {
rsa.publicEncrypt(new Buffer(2048));
}
assert.throws(f3, /too large/);
}


Expand Down

0 comments on commit 7997222

Please sign in to comment.