hmac check on rsa decrypt
This commit is contained in:
parent
4b9712d034
commit
8ff336d103
|
@ -10,7 +10,9 @@ function ConstantsService() {
|
||||||
AesCbc128_HmacSha256_B64: 1,
|
AesCbc128_HmacSha256_B64: 1,
|
||||||
AesCbc256_HmacSha256_B64: 2,
|
AesCbc256_HmacSha256_B64: 2,
|
||||||
Rsa2048_OaepSha256_B64: 3,
|
Rsa2048_OaepSha256_B64: 3,
|
||||||
Rsa2048_OaepSha1_B64: 4
|
Rsa2048_OaepSha1_B64: 4,
|
||||||
|
Rsa2048_OaepSha256_HmacSha256_B64: 5,
|
||||||
|
Rsa2048_OaepSha1_HmacSha256_B64: 6
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -427,7 +427,7 @@ function initCryptoService(constantsService) {
|
||||||
var iv = forge.util.encode64(ivBytes);
|
var iv = forge.util.encode64(ivBytes);
|
||||||
var ctBytes = cipher.output.getBytes();
|
var ctBytes = cipher.output.getBytes();
|
||||||
var ct = forge.util.encode64(ctBytes);
|
var ct = forge.util.encode64(ctBytes);
|
||||||
var mac = !key.macKey ? null : computeMac(ctBytes, ivBytes, key.macKey, true);
|
var mac = !key.macKey ? null : computeMac(ivBytes + ctBytes, key.macKey, true);
|
||||||
|
|
||||||
var cs = new CipherString(key.encType, iv, ct, mac);
|
var cs = new CipherString(key.encType, iv, ct, mac);
|
||||||
deferred.resolve(cs);
|
deferred.resolve(cs);
|
||||||
|
@ -473,7 +473,7 @@ function initCryptoService(constantsService) {
|
||||||
|
|
||||||
if (key.macKey && cipherString.mac) {
|
if (key.macKey && cipherString.mac) {
|
||||||
var macBytes = forge.util.decode64(cipherString.mac);
|
var macBytes = forge.util.decode64(cipherString.mac);
|
||||||
var computedMacBytes = computeMac(ctBytes, ivBytes, key.macKey, false);
|
var computedMacBytes = computeMac(ivBytes + ctBytes, key.macKey, false);
|
||||||
if (!macsEqual(key.macKey, computedMacBytes, macBytes)) {
|
if (!macsEqual(key.macKey, computedMacBytes, macBytes)) {
|
||||||
console.error('MAC failed.');
|
console.error('MAC failed.');
|
||||||
deferred.reject('MAC failed.');
|
deferred.reject('MAC failed.');
|
||||||
|
@ -503,38 +503,64 @@ function initCryptoService(constantsService) {
|
||||||
CryptoService.prototype.rsaDecrypt = function (encValue) {
|
CryptoService.prototype.rsaDecrypt = function (encValue) {
|
||||||
var headerPieces = encValue.split('.'),
|
var headerPieces = encValue.split('.'),
|
||||||
encType,
|
encType,
|
||||||
encPiece;
|
encPieces;
|
||||||
|
|
||||||
if (headerPieces.length === 1) {
|
if (headerPieces.length === 1) {
|
||||||
encType = constantsService.encType.Rsa2048_OaepSha256_B64;
|
encType = constantsService.encType.Rsa2048_OaepSha256_B64;
|
||||||
encPiece = headerPieces[0];
|
encPieces = [headerPieces[0]];
|
||||||
}
|
}
|
||||||
else if (headerPieces.length === 2) {
|
else if (headerPieces.length === 2) {
|
||||||
try {
|
try {
|
||||||
encType = parseInt(headerPieces[0]);
|
encType = parseInt(headerPieces[0]);
|
||||||
encPiece = headerPieces[1];
|
encPieces = headerPieces[1].split('|');
|
||||||
}
|
}
|
||||||
catch (e) { }
|
catch (e) { }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch (encType) {
|
||||||
|
case constantsService.encType.Rsa2048_OaepSha256_B64:
|
||||||
|
case constantsService.encType.Rsa2048_OaepSha1_B64:
|
||||||
|
if (encPieces.length !== 1) {
|
||||||
|
throw 'Invalid cipher format.';
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case constantsService.encType.Rsa2048_OaepSha256_HmacSha256_B64:
|
||||||
|
case constantsService.encType.Rsa2048_OaepSha1_HmacSha256_B64:
|
||||||
|
if (encPieces.length !== 2) {
|
||||||
|
throw 'Invalid cipher format.';
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw 'encType unavailable.';
|
||||||
|
}
|
||||||
|
|
||||||
var padding = null;
|
var padding = null;
|
||||||
if (encType === constantsService.encType.Rsa2048_OaepSha256_B64) {
|
switch (encType) {
|
||||||
|
case constantsService.encType.Rsa2048_OaepSha256_B64:
|
||||||
|
case constantsService.encType.Rsa2048_OaepSha256_HmacSha256_B64:
|
||||||
padding = {
|
padding = {
|
||||||
name: 'RSA-OAEP',
|
name: 'RSA-OAEP',
|
||||||
hash: { name: 'SHA-256' }
|
hash: { name: 'SHA-256' }
|
||||||
}
|
}
|
||||||
}
|
break;
|
||||||
else if (encType === constantsService.encType.Rsa2048_OaepSha1_B64) {
|
case constantsService.encType.Rsa2048_OaepSha1_B64:
|
||||||
|
case constantsService.encType.Rsa2048_OaepSha1_HmacSha256_B64:
|
||||||
padding = {
|
padding = {
|
||||||
name: 'RSA-OAEP',
|
name: 'RSA-OAEP',
|
||||||
hash: { name: 'SHA-1' }
|
hash: { name: 'SHA-1' }
|
||||||
}
|
}
|
||||||
}
|
break;
|
||||||
else {
|
default:
|
||||||
throw 'encType unavailable.';
|
throw 'encType unavailable.';
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.getPrivateKey().then(function (privateKeyBytes) {
|
var key = null,
|
||||||
|
self = this;
|
||||||
|
|
||||||
|
return self.getEncKey().then(function (encKey) {
|
||||||
|
key = encKey;
|
||||||
|
return self.getPrivateKey();
|
||||||
|
}).then(function (privateKeyBytes) {
|
||||||
if (!privateKeyBytes) {
|
if (!privateKeyBytes) {
|
||||||
throw 'No private key.';
|
throw 'No private key.';
|
||||||
}
|
}
|
||||||
|
@ -545,12 +571,21 @@ function initCryptoService(constantsService) {
|
||||||
|
|
||||||
return window.crypto.subtle.importKey('pkcs8', privateKeyBytes, padding, false, ['decrypt']);
|
return window.crypto.subtle.importKey('pkcs8', privateKeyBytes, padding, false, ['decrypt']);
|
||||||
}).then(function (privateKey) {
|
}).then(function (privateKey) {
|
||||||
if (!encPiece) {
|
if (!encPieces || !encPieces.length) {
|
||||||
throw 'encPiece unavailable.';
|
throw 'encPieces unavailable.';
|
||||||
}
|
}
|
||||||
|
|
||||||
var ctBytes = fromB64ToBuffer(encPiece);
|
if (key && key.macKey && encPieces.length > 1) {
|
||||||
return window.crypto.subtle.decrypt({ name: padding.name }, privateKey, ctBytes);
|
var ctBytes = forge.util.decode64(encPieces[0]);
|
||||||
|
var macBytes = forge.util.decode64(encPieces[1]);
|
||||||
|
var computedMacBytes = computeMac(ctBytes, key.macKey, false);
|
||||||
|
if (!macsEqual(key.macKey, macBytes, computedMacBytes)) {
|
||||||
|
throw 'MAC failed.';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var ctBuff = fromB64ToBuffer(encPieces[0]);
|
||||||
|
return window.crypto.subtle.decrypt({ name: padding.name }, privateKey, ctBuff);
|
||||||
}, function () {
|
}, function () {
|
||||||
throw 'Cannot import privateKey.';
|
throw 'Cannot import privateKey.';
|
||||||
}).then(function (decBytes) {
|
}).then(function (decBytes) {
|
||||||
|
@ -561,10 +596,10 @@ function initCryptoService(constantsService) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
function computeMac(ct, iv, macKey, b64Output) {
|
function computeMac(dataBytes, macKey, b64Output) {
|
||||||
var hmac = forge.hmac.create();
|
var hmac = forge.hmac.create();
|
||||||
hmac.start('sha256', macKey);
|
hmac.start('sha256', macKey);
|
||||||
hmac.update(iv + ct);
|
hmac.update(dataBytes);
|
||||||
var mac = hmac.digest();
|
var mac = hmac.digest();
|
||||||
return b64Output ? forge.util.encode64(mac.getBytes()) : mac.getBytes();
|
return b64Output ? forge.util.encode64(mac.getBytes()) : mac.getBytes();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue