has been computed from the given data. Should be called after
encryption has been completed using the `final` method!
+### cipher.setAAD(buffer)
+
+For authenticated encryption modes (currently supported: GCM), this
+method sets the value used for the additional authenticated data (AAD) input
+parameter.
+
## crypto.createDecipher(algorithm, password)
`final` will throw, thus indicating that the ciphertext should
be discarded due to failed authentication.
+### decipher.setAAD(buffer)
+
+For authenticated encryption modes (currently supported: GCM), this
+method sets the value used for the additional authenticated data (AAD) input
+parameter.
+
## crypto.createSign(algorithm)
this._binding.setAuthTag(tagbuf);
};
+Cipheriv.prototype.setAAD = function(aadbuf) {
+ this._binding.setAAD(aadbuf);
+};
exports.createDecipher = exports.Decipher = Decipher;
Decipheriv.prototype.setAutoPadding = Cipher.prototype.setAutoPadding;
Decipheriv.prototype.getAuthTag = Cipheriv.prototype.getAuthTag;
Decipheriv.prototype.setAuthTag = Cipheriv.prototype.setAuthTag;
+Decipheriv.prototype.setAAD = Cipheriv.prototype.setAAD;
NODE_SET_PROTOTYPE_METHOD(t, "setAutoPadding", SetAutoPadding);
NODE_SET_PROTOTYPE_METHOD(t, "getAuthTag", GetAuthTag);
NODE_SET_PROTOTYPE_METHOD(t, "setAuthTag", SetAuthTag);
+ NODE_SET_PROTOTYPE_METHOD(t, "setAAD", SetAAD);
target->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "CipherBase"),
t->GetFunction());
}
+bool CipherBase::SetAAD(const char* data, unsigned int len) {
+ if (!initialised_ || !IsAuthenticatedMode())
+ return false;
+ int outlen;
+ if (!EVP_CipherUpdate(&ctx_,
+ NULL,
+ &outlen,
+ reinterpret_cast<const unsigned char*>(data),
+ len)) {
+ ThrowCryptoTypeError(env(), ERR_get_error());
+ return false;
+ }
+ return true;
+}
+
+
+void CipherBase::SetAAD(const FunctionCallbackInfo<Value>& args) {
+ Environment* env = Environment::GetCurrent(args.GetIsolate());
+ HandleScope handle_scope(env->isolate());
+
+ ASSERT_IS_BUFFER(args[0]);
+
+ CipherBase* cipher = Unwrap<CipherBase>(args.This());
+
+ if (!cipher->SetAAD(Buffer::Data(args[0]), Buffer::Length(args[0])))
+ env->ThrowError("Attempting to set AAD in unsupported state");
+}
+
+
bool CipherBase::Update(const char* data,
int len,
unsigned char** out,
bool IsAuthenticatedMode() const;
bool GetAuthTag(char** out, unsigned int* out_len) const;
bool SetAuthTag(const char* data, unsigned int len);
+ bool SetAAD(const char* data, unsigned int len);
static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
static void Init(const v8::FunctionCallbackInfo<v8::Value>& args);
static void GetAuthTag(const v8::FunctionCallbackInfo<v8::Value>& args);
static void SetAuthTag(const v8::FunctionCallbackInfo<v8::Value>& args);
+ static void SetAAD(const v8::FunctionCallbackInfo<v8::Value>& args);
CipherBase(Environment* env,
v8::Local<v8::Object> wrap,
//
var TEST_CASES = [
- { algo: 'aes-128-gcm', key: 'ipxp9a6i1Mb4USb4', iv: 'X6sIq117H0vR',
- plain: 'Hello World!', ct: '4BE13896F64DFA2C2D0F2C76',
+ { algo: 'aes-128-gcm', key: 'ipxp9a6i1Mb4USb4',
+ iv: 'X6sIq117H0vR', plain: 'Hello World!',
+ ct: '4BE13896F64DFA2C2D0F2C76',
tag: '272B422F62EB545EAA15B5FF84092447', tampered: false },
- { algo: 'aes-128-gcm', key: 'ipxp9a6i1Mb4USb4', iv: 'X6sIq117H0vR',
- plain: 'Hello World!', ct: '4BE13596F64DFA2C2D0FAC76',
+ { algo: 'aes-128-gcm', key: 'ipxp9a6i1Mb4USb4',
+ iv: 'X6sIq117H0vR', plain: 'Hello World!',
+ ct: '4BE13896F64DFA2C2D0F2C76', aad: '000000FF',
+ tag: 'BA2479F66275665A88CB7B15F43EB005', tampered: false },
+ { algo: 'aes-128-gcm', key: 'ipxp9a6i1Mb4USb4',
+ iv: 'X6sIq117H0vR', plain: 'Hello World!',
+ ct: '4BE13596F64DFA2C2D0FAC76',
tag: '272B422F62EB545EAA15B5FF84092447', tampered: true },
{ algo: 'aes-256-gcm', key: '3zTvzr3p67VC61jmV54rIYu1545x4TlY',
iv: '60iP0h6vJoEa', plain: 'Hello node.js world!',
(function() {
var encrypt = crypto.createCipheriv(test.algo, test.key, test.iv);
+ if (test.aad)
+ encrypt.setAAD(new Buffer(test.aad, 'hex'));
var hex = encrypt.update(test.plain, 'ascii', 'hex');
hex += encrypt.final('hex');
var auth_tag = encrypt.getAuthTag();
(function() {
var decrypt = crypto.createDecipheriv(test.algo, test.key, test.iv);
decrypt.setAuthTag(new Buffer(test.tag, 'hex'));
+ if (test.aad)
+ decrypt.setAAD(new Buffer(test.aad, 'hex'));
var msg = decrypt.update(test.ct, 'hex', 'ascii');
if (!test.tampered) {
msg += decrypt.final('ascii');