Skip to content

Commit 44b9d08

Browse files
tniessencodebytere
authored andcommitted
src: add NativeKeyObject base class
+---------------------+ | BaseObject | +---------------------+ | | | +---------------------+ | NativeKeyObject | +---------------------+ | | | +---------------------+ | KeyObject | +---------------------+ / \ / \ / \ / \ +---------------------+ +---------------------+ | SecretKeyObject | | AsymmetricKeyObject | +---------------------+ +---------------------+ / \ / \ / \ / \ +---------------------+ +---------------------+ | PublicKeyObject | | PrivateKeyObject | +---------------------+ +---------------------+ PR-URL: #33360 Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: James M Snell <[email protected]>
1 parent 13e6338 commit 44b9d08

File tree

3 files changed

+112
-59
lines changed

3 files changed

+112
-59
lines changed

lib/internal/crypto/keys.js

+76-59
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ const {
77

88
const {
99
KeyObjectHandle,
10+
createNativeKeyObjectClass,
1011
kKeyTypeSecret,
1112
kKeyTypePublic,
1213
kKeyTypePrivate,
@@ -42,80 +43,96 @@ for (const m of [[kKeyEncodingPKCS1, 'pkcs1'], [kKeyEncodingPKCS8, 'pkcs8'],
4243
[kKeyEncodingSPKI, 'spki'], [kKeyEncodingSEC1, 'sec1']])
4344
encodingNames[m[0]] = m[1];
4445

45-
class KeyObject {
46-
constructor(type, handle) {
47-
if (type !== 'secret' && type !== 'public' && type !== 'private')
48-
throw new ERR_INVALID_ARG_VALUE('type', type);
49-
if (typeof handle !== 'object')
50-
throw new ERR_INVALID_ARG_TYPE('handle', 'object', handle);
51-
52-
this[kKeyType] = type;
53-
54-
ObjectDefineProperty(this, kHandle, {
55-
value: handle,
56-
enumerable: false,
57-
configurable: false,
58-
writable: false
59-
});
60-
}
46+
// Creating the KeyObject class is a little complicated due to inheritance
47+
// and that fact that KeyObjects should be transferrable between threads,
48+
// which requires the KeyObject base class to be implemented in C++.
49+
// The creation requires a callback to make sure that the NativeKeyObject
50+
// base class cannot exist without the other KeyObject implementations.
51+
const [
52+
KeyObject,
53+
SecretKeyObject,
54+
PublicKeyObject,
55+
PrivateKeyObject
56+
] = createNativeKeyObjectClass((NativeKeyObject) => {
57+
// Publicly visible KeyObject class.
58+
class KeyObject extends NativeKeyObject {
59+
constructor(type, handle) {
60+
super();
61+
if (type !== 'secret' && type !== 'public' && type !== 'private')
62+
throw new ERR_INVALID_ARG_VALUE('type', type);
63+
if (typeof handle !== 'object')
64+
throw new ERR_INVALID_ARG_TYPE('handle', 'object', handle);
65+
66+
this[kKeyType] = type;
67+
68+
ObjectDefineProperty(this, kHandle, {
69+
value: handle,
70+
enumerable: false,
71+
configurable: false,
72+
writable: false
73+
});
74+
}
6175

62-
get type() {
63-
return this[kKeyType];
76+
get type() {
77+
return this[kKeyType];
78+
}
6479
}
65-
}
6680

67-
class SecretKeyObject extends KeyObject {
68-
constructor(handle) {
69-
super('secret', handle);
70-
}
81+
class SecretKeyObject extends KeyObject {
82+
constructor(handle) {
83+
super('secret', handle);
84+
}
7185

72-
get symmetricKeySize() {
73-
return this[kHandle].getSymmetricKeySize();
74-
}
86+
get symmetricKeySize() {
87+
return this[kHandle].getSymmetricKeySize();
88+
}
7589

76-
export() {
77-
return this[kHandle].export();
90+
export() {
91+
return this[kHandle].export();
92+
}
7893
}
79-
}
8094

81-
const kAsymmetricKeyType = Symbol('kAsymmetricKeyType');
95+
const kAsymmetricKeyType = Symbol('kAsymmetricKeyType');
8296

83-
class AsymmetricKeyObject extends KeyObject {
84-
get asymmetricKeyType() {
85-
return this[kAsymmetricKeyType] ||
86-
(this[kAsymmetricKeyType] = this[kHandle].getAsymmetricKeyType());
97+
class AsymmetricKeyObject extends KeyObject {
98+
get asymmetricKeyType() {
99+
return this[kAsymmetricKeyType] ||
100+
(this[kAsymmetricKeyType] = this[kHandle].getAsymmetricKeyType());
101+
}
87102
}
88-
}
89103

90-
class PublicKeyObject extends AsymmetricKeyObject {
91-
constructor(handle) {
92-
super('public', handle);
93-
}
104+
class PublicKeyObject extends AsymmetricKeyObject {
105+
constructor(handle) {
106+
super('public', handle);
107+
}
94108

95-
export(encoding) {
96-
const {
97-
format,
98-
type
99-
} = parsePublicKeyEncoding(encoding, this.asymmetricKeyType);
100-
return this[kHandle].export(format, type);
109+
export(encoding) {
110+
const {
111+
format,
112+
type
113+
} = parsePublicKeyEncoding(encoding, this.asymmetricKeyType);
114+
return this[kHandle].export(format, type);
115+
}
101116
}
102-
}
103117

104-
class PrivateKeyObject extends AsymmetricKeyObject {
105-
constructor(handle) {
106-
super('private', handle);
107-
}
118+
class PrivateKeyObject extends AsymmetricKeyObject {
119+
constructor(handle) {
120+
super('private', handle);
121+
}
108122

109-
export(encoding) {
110-
const {
111-
format,
112-
type,
113-
cipher,
114-
passphrase
115-
} = parsePrivateKeyEncoding(encoding, this.asymmetricKeyType);
116-
return this[kHandle].export(format, type, cipher, passphrase);
123+
export(encoding) {
124+
const {
125+
format,
126+
type,
127+
cipher,
128+
passphrase
129+
} = parsePrivateKeyEncoding(encoding, this.asymmetricKeyType);
130+
return this[kHandle].export(format, type, cipher, passphrase);
131+
}
117132
}
118-
}
133+
134+
return [KeyObject, SecretKeyObject, PublicKeyObject, PrivateKeyObject];
135+
});
119136

120137
function parseKeyFormat(formatStr, defaultFormat, optionName) {
121138
if (formatStr === undefined && defaultFormat !== undefined)

src/node_crypto.cc

+27
Original file line numberDiff line numberDiff line change
@@ -3468,6 +3468,31 @@ MaybeLocal<Value> KeyObjectHandle::ExportPrivateKey(
34683468
return WritePrivateKey(env(), asymmetric_key_.get(), config);
34693469
}
34703470

3471+
void NativeKeyObject::New(const FunctionCallbackInfo<Value>& args) {
3472+
CHECK_EQ(args.Length(), 0);
3473+
}
3474+
3475+
static void CreateNativeKeyObjectClass(
3476+
const FunctionCallbackInfo<Value>& args) {
3477+
Environment* env = Environment::GetCurrent(args);
3478+
3479+
CHECK_EQ(args.Length(), 1);
3480+
Local<Value> callback = args[0];
3481+
CHECK(callback->IsFunction());
3482+
3483+
Local<FunctionTemplate> t = env->NewFunctionTemplate(NativeKeyObject::New);
3484+
t->InstanceTemplate()->SetInternalFieldCount(
3485+
KeyObjectHandle::kInternalFieldCount);
3486+
3487+
Local<Value> ctor = t->GetFunction(env->context()).ToLocalChecked();
3488+
3489+
Local<Value> recv = Undefined(env->isolate());
3490+
Local<Value> ret =
3491+
callback.As<Function>()->Call(env->context(), recv, 1, &ctor)
3492+
.ToLocalChecked();
3493+
args.GetReturnValue().Set(ret);
3494+
}
3495+
34713496
CipherBase::CipherBase(Environment* env,
34723497
Local<Object> wrap,
34733498
CipherKind kind)
@@ -6871,6 +6896,8 @@ void Initialize(Local<Object> target,
68716896
SecureContext::Initialize(env, target);
68726897
env->set_crypto_key_object_handle_constructor(
68736898
KeyObjectHandle::Initialize(env, target));
6899+
env->SetMethod(target, "createNativeKeyObjectClass",
6900+
CreateNativeKeyObjectClass);
68746901
CipherBase::Initialize(env, target);
68756902
DiffieHellman::Initialize(env, target);
68766903
ECDH::Initialize(env, target);

src/node_crypto.h

+9
Original file line numberDiff line numberDiff line change
@@ -463,6 +463,15 @@ class KeyObjectHandle : public BaseObject {
463463
ManagedEVPPKey asymmetric_key_;
464464
};
465465

466+
class NativeKeyObject : public BaseObject {
467+
public:
468+
static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
469+
470+
SET_NO_MEMORY_INFO()
471+
SET_MEMORY_INFO_NAME(NativeKeyObject)
472+
SET_SELF_SIZE(NativeKeyObject)
473+
};
474+
466475
class CipherBase : public BaseObject {
467476
public:
468477
static void Initialize(Environment* env, v8::Local<v8::Object> target);

0 commit comments

Comments
 (0)