Commit 32fdefdd authored by ap@apple.com's avatar ap@apple.com

Implement raw format for WebCrypto key export

https://bugs.webkit.org/show_bug.cgi?id=124376

Reviewed by Anders Carlsson.

Source/WebCore: 

Tests: crypto/subtle/aes-export-key.html
       crypto/subtle/hmac-export-key.html

A CryptoKey just exports its native CryptoKeyData, which will also work nicely for
JWK format soon. For spki and pkcs8, we'll need to figure out the best way to
utilize platform library support for ASN.1, but we are not there yet.

* bindings/js/JSSubtleCryptoCustom.cpp:
(WebCore::JSSubtleCrypto::exportKey):
* crypto/CryptoKey.h:
* crypto/SubtleCrypto.idl:
* crypto/keys/CryptoKeyAES.cpp:
(WebCore::CryptoKeyAES::exportData):
* crypto/keys/CryptoKeyAES.h:
* crypto/keys/CryptoKeyHMAC.cpp:
(WebCore::CryptoKeyHMAC::exportData):
* crypto/keys/CryptoKeyHMAC.h:

* crypto/keys/CryptoKeyRSA.h:
* crypto/mac/CryptoKeyRSAMac.cpp:
(WebCore::CryptoKeyRSA::exportData):
Added a dummy implementation for RSA.

LayoutTests: 

* crypto/subtle/aes-export-key-expected.txt: Added.
* crypto/subtle/aes-export-key.html: Added.
* crypto/subtle/hmac-export-key-expected.txt: Added.
* crypto/subtle/hmac-export-key.html: Added.



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@159310 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 4617b9e6
2013-11-14 Alexey Proskuryakov <ap@apple.com>
Implement raw format for WebCrypto key export
https://bugs.webkit.org/show_bug.cgi?id=124376
Reviewed by Anders Carlsson.
* crypto/subtle/aes-export-key-expected.txt: Added.
* crypto/subtle/aes-export-key.html: Added.
* crypto/subtle/hmac-export-key-expected.txt: Added.
* crypto/subtle/hmac-export-key.html: Added.
2013-11-14 Bear Travis <betravis@adobe.com>
[CSS Shapes] Accept the new <box> value for shape-outside
......
Test exporting an AES key.
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
Importing a JWK key...
Exporting the key as raw data...
PASS byteArrayToHexString(new Uint8Array(exportedData)) is '[8e 73 b0 f7 da 0e 64 52 c8 10 f3 2b 80 90 79 e5 62 f8 ea d2 52 2c 6b 7b]'
PASS successfullyParsed is true
TEST COMPLETE
<!DOCTYPE html>
<html>
<head>
<script src="../../resources/js-test-pre.js"></script>
<script src="resources/common.js"></script>
</head>
<body>
<p id="description"></p>
<div id="console"></div>
<script>
description("Test exporting an AES key.");
jsTestIsAsync = true;
if (!window.subtle)
window.crypto.subtle = window.crypto.webkitSubtle;
var extractable = true;
var jwkKey = {
"kty": "oct",
"k": "jnOw99oOZFLIEPMrgJB55WL46tJSLGt7"
};
var jwkKeyAsArrayBuffer = asciiToArrayBuffer(JSON.stringify(jwkKey));
debug("Importing a JWK key...");
crypto.subtle.importKey("jwk", jwkKeyAsArrayBuffer, "AES-CBC", extractable, []).then(function(result) {
key = result;
debug("Exporting the key as raw data...");
return crypto.subtle.exportKey("raw", key);
}).then(function(result) {
exportedData = result;
shouldBe("byteArrayToHexString(new Uint8Array(exportedData))", "'[8e 73 b0 f7 da 0e 64 52 c8 10 f3 2b 80 90 79 e5 62 f8 ea d2 52 2c 6b 7b]'");
finishJSTest();
});
</script>
<script src="../../resources/js-test-post.js"></script>
</body>
</html>
Test exporting an AES key.
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
Importing a JWK key...
Exporting the key as raw data...
PASS byteArrayToHexString(new Uint8Array(exportedData)) is '[6a 18 e4 9f ef f7 f3 b7 e0 9e c8 9b 7f 6d ea b2 f6 a1 8e 49 fe ff 7f 3b 7e 09 ec 89 b7 f6 de ab]'
PASS successfullyParsed is true
TEST COMPLETE
<!DOCTYPE html>
<html>
<head>
<script src="../../resources/js-test-pre.js"></script>
<script src="resources/common.js"></script>
</head>
<body>
<p id="description"></p>
<div id="console"></div>
<script>
description("Test exporting an AES key.");
jsTestIsAsync = true;
if (!window.subtle)
window.crypto.subtle = window.crypto.webkitSubtle;
var extractable = true;
var jwkKey = {
"kty": "oct",
"k": "ahjkn-_387fgnsibf23qsvahjkn-_387fgnsibf23qs"
};
var jwkKeyAsArrayBuffer = asciiToArrayBuffer(JSON.stringify(jwkKey));
debug("Importing a JWK key...");
crypto.subtle.importKey("jwk", jwkKeyAsArrayBuffer, { name: "HMAC", hash: "SHA-512" }, extractable, ["sign", "verify"]).then(function(result) {
key = result;
debug("Exporting the key as raw data...");
return crypto.subtle.exportKey("raw", key);
}).then(function(result) {
exportedData = result;
shouldBe("byteArrayToHexString(new Uint8Array(exportedData))", "'[6a 18 e4 9f ef f7 f3 b7 e0 9e c8 9b 7f 6d ea b2 f6 a1 8e 49 fe ff 7f 3b 7e 09 ec 89 b7 f6 de ab]'");
finishJSTest();
});
</script>
<script src="../../resources/js-test-post.js"></script>
</body>
</html>
2013-11-14 Alexey Proskuryakov <ap@apple.com>
Implement raw format for WebCrypto key export
https://bugs.webkit.org/show_bug.cgi?id=124376
Reviewed by Anders Carlsson.
Tests: crypto/subtle/aes-export-key.html
crypto/subtle/hmac-export-key.html
A CryptoKey just exports its native CryptoKeyData, which will also work nicely for
JWK format soon. For spki and pkcs8, we'll need to figure out the best way to
utilize platform library support for ASN.1, but we are not there yet.
* bindings/js/JSSubtleCryptoCustom.cpp:
(WebCore::JSSubtleCrypto::exportKey):
* crypto/CryptoKey.h:
* crypto/SubtleCrypto.idl:
* crypto/keys/CryptoKeyAES.cpp:
(WebCore::CryptoKeyAES::exportData):
* crypto/keys/CryptoKeyAES.h:
* crypto/keys/CryptoKeyHMAC.cpp:
(WebCore::CryptoKeyHMAC::exportData):
* crypto/keys/CryptoKeyHMAC.h:
* crypto/keys/CryptoKeyRSA.h:
* crypto/mac/CryptoKeyRSAMac.cpp:
(WebCore::CryptoKeyRSA::exportData):
Added a dummy implementation for RSA.
2013-11-14 Joseph Pecoraro <pecoraro@apple.com>
Web Inspector: Simply generated domain dispatch methods for domains with few commands
......
......@@ -32,6 +32,8 @@
#include "CryptoAlgorithmParameters.h"
#include "CryptoAlgorithmRegistry.h"
#include "CryptoKeyData.h"
#include "CryptoKeyDataOctetSequence.h"
#include "CryptoKeyDataRSAComponents.h"
#include "CryptoKeySerializationRaw.h"
#include "Document.h"
#include "ExceptionCode.h"
......@@ -506,6 +508,56 @@ JSValue JSSubtleCrypto::importKey(JSC::ExecState* exec)
return promise;
}
JSValue JSSubtleCrypto::exportKey(JSC::ExecState* exec)
{
if (exec->argumentCount() < 2)
return exec->vm().throwException(exec, createNotEnoughArgumentsError(exec));
CryptoKeyFormat keyFormat;
if (!cryptoKeyFormatFromJSValue(exec, exec->argument(0), keyFormat)) {
ASSERT(exec->hadException());
return jsUndefined();
}
RefPtr<CryptoKey> key = toCryptoKey(exec->uncheckedArgument(1));
if (!key)
return throwTypeError(exec);
JSPromise* promise = JSPromise::createWithResolver(exec->vm(), globalObject());
auto promiseWrapper = PromiseWrapper::create(globalObject(), promise);
if (!key->extractable()) {
m_impl->document()->addConsoleMessage(JSMessageSource, ErrorMessageLevel, "Key is not extractable");
promiseWrapper->reject(nullptr);
return promise;
}
std::unique_ptr<CryptoKeyData> keyData = key->exportData();
if (!keyData) {
// FIXME: Shouldn't happen once all key types implement exportData().
promiseWrapper->reject(nullptr);
return promise;
}
switch (keyFormat) {
case CryptoKeyFormat::Raw:
if (isCryptoKeyDataOctetSequence(*keyData)) {
Vector<unsigned char> result;
result.appendVector(toCryptoKeyDataOctetSequence(*keyData).octetSequence());
promiseWrapper->fulfill(result);
} else {
m_impl->document()->addConsoleMessage(JSMessageSource, ErrorMessageLevel, "Key cannot be exported to raw format");
promiseWrapper->reject(nullptr);
}
break;
default:
throwTypeError(exec, "Unsupported key format");
return jsUndefined();
}
return promise;
}
} // namespace WebCore
#endif
......@@ -38,6 +38,7 @@
namespace WebCore {
class CryptoAlgorithmDescriptionBuilder;
class CryptoKeyData;
ENUM_CLASS(CryptoKeyClass) {
HMAC,
......@@ -59,6 +60,8 @@ public:
bool allows(CryptoKeyUsage usage) const { return usage == (m_usages & usage); }
virtual std::unique_ptr<CryptoKeyData> exportData() const = 0;
static Vector<char> randomData(size_t);
private:
......
......@@ -36,4 +36,5 @@
[Custom] Promise digest(AlgorithmIdentifier algorithm, sequence<CryptoOperationData> data);
[Custom] Promise generateKey(AlgorithmIdentifier algorithm, optional boolean extractable, optional KeyUsage[] keyUsages);
[Custom] Promise importKey(KeyFormat format, CryptoOperationData keyData, AlgorithmIdentifier? algorithm, optional boolean extractable, optional KeyUsage[] keyUsages);
[Custom] Promise exportKey(KeyFormat format, Key key);
};
......@@ -30,6 +30,7 @@
#include "CryptoAlgorithmDescriptionBuilder.h"
#include "CryptoAlgorithmRegistry.h"
#include "CryptoKeyDataOctetSequence.h"
#include <wtf/text/WTFString.h>
namespace WebCore {
......@@ -62,6 +63,12 @@ void CryptoKeyAES::buildAlgorithmDescription(CryptoAlgorithmDescriptionBuilder&
builder.add("length", m_key.size() * 8);
}
std::unique_ptr<CryptoKeyData> CryptoKeyAES::exportData() const
{
ASSERT(extractable());
return CryptoKeyDataOctetSequence::create(m_key);
}
} // namespace WebCore
#endif // ENABLE(SUBTLE_CRYPTO)
......@@ -48,11 +48,12 @@ public:
const Vector<char>& key() const { return m_key; }
virtual void buildAlgorithmDescription(CryptoAlgorithmDescriptionBuilder&) const OVERRIDE;
private:
CryptoKeyAES(CryptoAlgorithmIdentifier, const Vector<char>& key, bool extractable, CryptoKeyUsage);
virtual void buildAlgorithmDescription(CryptoAlgorithmDescriptionBuilder&) const OVERRIDE;
virtual std::unique_ptr<CryptoKeyData> exportData() const OVERRIDE;
Vector<char> m_key;
};
......
......@@ -30,6 +30,7 @@
#include "CryptoAlgorithmDescriptionBuilder.h"
#include "CryptoAlgorithmRegistry.h"
#include "CryptoKeyDataOctetSequence.h"
#include <wtf/text/WTFString.h>
namespace WebCore {
......@@ -77,6 +78,12 @@ void CryptoKeyHMAC::buildAlgorithmDescription(CryptoAlgorithmDescriptionBuilder&
builder.add("length", m_key.size());
}
std::unique_ptr<CryptoKeyData> CryptoKeyHMAC::exportData() const
{
ASSERT(extractable());
return CryptoKeyDataOctetSequence::create(m_key);
}
} // namespace WebCore
#endif // ENABLE(SUBTLE_CRYPTO)
......@@ -48,11 +48,12 @@ public:
const Vector<char>& key() const { return m_key; }
virtual void buildAlgorithmDescription(CryptoAlgorithmDescriptionBuilder&) const OVERRIDE;
private:
CryptoKeyHMAC(const Vector<char>& key, CryptoAlgorithmIdentifier hash, bool extractable, CryptoKeyUsage);
virtual void buildAlgorithmDescription(CryptoAlgorithmDescriptionBuilder&) const OVERRIDE;
virtual std::unique_ptr<CryptoKeyData> exportData() const OVERRIDE;
CryptoAlgorithmIdentifier m_hash;
Vector<char> m_key;
};
......
......@@ -58,11 +58,12 @@ public:
PlatformRSAKey platformKey() const { return m_platformKey; }
virtual void buildAlgorithmDescription(CryptoAlgorithmDescriptionBuilder&) const OVERRIDE;
private:
CryptoKeyRSA(CryptoAlgorithmIdentifier, CryptoKeyType, PlatformRSAKey, bool extractable, CryptoKeyUsage);
virtual void buildAlgorithmDescription(CryptoAlgorithmDescriptionBuilder&) const OVERRIDE;
virtual std::unique_ptr<CryptoKeyData> exportData() const OVERRIDE;
PlatformRSAKey m_platformKey;
bool m_restrictedToSpecificHash;
......
......@@ -143,6 +143,13 @@ void CryptoKeyRSA::buildAlgorithmDescription(CryptoAlgorithmDescriptionBuilder&
}
}
std::unique_ptr<CryptoKeyData> CryptoKeyRSA::exportData() const
{
// Not implemented yet.
ASSERT(extractable());
return nullptr;
}
static bool bigIntegerToUInt32(const Vector<char>& bigInteger, uint32_t& result)
{
result = 0;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment