Bug 1034855 - Implement deriveKey() for ECDH r=rbarnes

This commit is contained in:
Tim Taubert 2014-07-29 12:37:06 +02:00
parent 5b5fc12a02
commit ad2acd36ae
2 changed files with 67 additions and 11 deletions

View File

@ -2327,17 +2327,18 @@ private:
}
};
class DerivePbkdfKeyTask : public DerivePbkdfBitsTask
template<class DeriveBitsTask>
class DeriveKeyTask : public DeriveBitsTask
{
public:
DerivePbkdfKeyTask(JSContext* aCx,
const ObjectOrString& aAlgorithm, CryptoKey& aBaseKey,
const ObjectOrString& aDerivedKeyType, bool aExtractable,
const Sequence<nsString>& aKeyUsages)
: DerivePbkdfBitsTask(aCx, aAlgorithm, aBaseKey, aDerivedKeyType)
DeriveKeyTask(JSContext* aCx,
const ObjectOrString& aAlgorithm, CryptoKey& aBaseKey,
const ObjectOrString& aDerivedKeyType, bool aExtractable,
const Sequence<nsString>& aKeyUsages)
: DeriveBitsTask(aCx, aAlgorithm, aBaseKey, aDerivedKeyType)
, mResolved(false)
{
if (NS_FAILED(mEarlyRv)) {
if (NS_FAILED(this->mEarlyRv)) {
return;
}
@ -2352,8 +2353,8 @@ protected:
private:
virtual void Resolve() MOZ_OVERRIDE {
mTask->SetKeyData(mResult);
mTask->DispatchWithPromise(mResultPromise);
mTask->SetKeyData(this->mResult);
mTask->DispatchWithPromise(this->mResultPromise);
mResolved = true;
}
@ -2737,8 +2738,15 @@ WebCryptoTask::CreateDeriveKeyTask(JSContext* aCx,
}
if (algName.EqualsASCII(WEBCRYPTO_ALG_PBKDF2)) {
return new DerivePbkdfKeyTask(aCx, aAlgorithm, aBaseKey, aDerivedKeyType,
aExtractable, aKeyUsages);
return new DeriveKeyTask<DerivePbkdfBitsTask>(aCx, aAlgorithm, aBaseKey,
aDerivedKeyType, aExtractable,
aKeyUsages);
}
if (algName.EqualsASCII(WEBCRYPTO_ALG_ECDH)) {
return new DeriveKeyTask<DeriveEcdhBitsTask>(aCx, aAlgorithm, aBaseKey,
aDerivedKeyType, aExtractable,
aKeyUsages);
}
return new FailureTask(NS_ERROR_DOM_NOT_SUPPORTED_ERR);

View File

@ -2143,3 +2143,51 @@ TestArray.addTest(
.then(error(that), complete(that));
}
);
// -----------------------------------------------------------------------------
TestArray.addTest(
"Derive an HMAC key from two ECDH keys and test sign/verify",
function() {
var that = this;
var alg = { name: "ECDH" };
var algDerived = { name: "HMAC", hash: {name: "SHA-1"} };
var pubKey, privKey;
function setPub(x) { pubKey = x; }
function setPriv(x) { privKey = x; }
function doDerive() {
var alg = { name: "ECDH", public: pubKey };
return crypto.subtle.deriveKey(alg, privKey, algDerived, false, ["sign", "verify"])
.then(function (x) {
if (!hasKeyFields(x)) {
throw "Invalid key; missing field(s)";
}
// 512 bit is the default for HMAC-SHA1.
if (x.algorithm.length != 512) {
throw "Invalid key; incorrect length";
}
return x;
});
}
function doSignAndVerify(x) {
var data = crypto.getRandomValues(new Uint8Array(1024));
return crypto.subtle.sign("HMAC", x, data)
.then(function (sig) {
return crypto.subtle.verify("HMAC", x, sig, data);
});
}
Promise.all([
crypto.subtle.importKey("jwk", tv.ecdh_p521.jwk_priv, alg, false, ["deriveBits"])
.then(setPriv, error(that)),
crypto.subtle.importKey("jwk", tv.ecdh_p521.jwk_pub, alg, false, ["deriveBits"])
.then(setPub, error(that))
]).then(doDerive, error(that))
.then(doSignAndVerify, error(that))
.then(complete(that), error(that));
}
);