Baseline Widely available *
å®å ¨ãªã³ã³ããã¹ãç¨: ãã®æ©è½ã¯ä¸é¨ã¾ãã¯ãã¹ã¦ã®å¯¾å¿ãã¦ãããã©ã¦ã¶ã¼ã«ããã¦ãå®å ¨ãªã³ã³ããã¹ã (HTTPS) ã§ã®ã¿å©ç¨ã§ãã¾ãã
ã¡ã¢: ãã®æ©è½ã¯ã¦ã§ãã¯ã¼ã«ã¼å ã§å©ç¨å¯è½ã§ãã
deriveKey()
㯠SubtleCrypto
ã¤ã³ã¿ã¼ãã§ã¤ã¹ã®ã¡ã½ããã§ããã¹ã¿ã¼éµããç§å¯éµãå°åºããããã«ä½¿ç¨ãããã¨ãã§ãã¾ãã
弿°ã¨ãã¦ãåæéµç´ æã使ç¨ããå°åºã¢ã«ã´ãªãºã ãå°åºããéµã«å¿
è¦ãªããããã£ãåãã¾ãã ããã¯æ°ããéµã表ã CryptoKey
ãªãã¸ã§ã¯ãã§å±¥è¡ããã Promise
ãè¿ãã¾ãã
ãªãã対å¿ãã¦ããéµå°åºã¢ã«ã´ãªãºã ã¯ãããããã¾ã£ããç°ãªãç¹æ§ãæã£ã¦ãããé©ãã¦ããç¶æ³ãã¾ã£ããç°ãªãã¾ãã ãã®è©³ç´°ã¯ã対å¿ãã¦ããã¢ã«ã´ãªãºã ãåç §ãã¦ãã ããã
æ§æderiveKey(algorithm, baseKey, derivedKeyAlgorithm, extractable, keyUsages)
弿°
algorithm
使ç¨ãã¦ããå°åºã¢ã«ã´ãªãºã ãå®ç¾©ãããªãã¸ã§ã¯ãã
EcdhKeyDeriveParams
ãªãã¸ã§ã¯ããæ¸¡ããæåå ECDH
ã name
ããããã£ã«æå®ãã¦ãã ãããHkdfParams
ãªãã¸ã§ã¯ããæ¸¡ãã¦ãã ãããPbkdf2Params
ãªãã¸ã§ã¯ããæ¸¡ãã¦ãã ãããEcdhKeyDeriveParams
ãªãã¸ã§ã¯ããæ¸¡ããæåå X25519
ã name
ããããã£ã«æå®ãã¦ãã ãããbaseKey
å°åºã¢ã«ã´ãªãºã ã¸ã®å
¥åã表ã CryptoKey
ã§ãã algorithm
ã ECDH ã¾ã㯠X25519 ã§ããå ´åããã㯠ECDH ã¾ã㯠X25519 ã®ç§å¯éµã¨ãªãã¾ãã ãã以å¤ã®å ´åãããã¯å°åºé¢æ°ã®åæãã¼ç´ æã«ãªãã¾ããä¾ãã°ã PBKDF2 ã®å ´åã SubtleCrypto.importKey()
ã使ç¨ã㦠CryptoKey
ã¨ãã¦ã¤ã³ãã¼ããããã¹ã¯ã¼ãã«ãªãã¾ãã
derivedKeyAlgorithm
å°åºéµã使ç¨ããã¢ã«ã´ãªãºã ãå®ç¾©ãããªãã¸ã§ã¯ãã§ãã
HmacKeyGenParams
ãªãã¸ã§ã¯ããæ¸¡ãã¦ãã ãããAesKeyGenParams
ãªãã¸ã§ã¯ããæ¸¡ãã¦ãã ãããHkdfParams
ãªãã¸ã§ã¯ããæ¸¡ãã¦ãã ãããPbkdf2Params
ãªãã¸ã§ã¯ããæ¸¡ãã¦ãã ãããè«çå¤ã§ã SubtleCrypto.exportKey()
ã¾ã㯠SubtleCrypto.wrapKey()
ã使ç¨ãã¦éµãã¨ã¯ã¹ãã¼ããããã¨ãå¯è½ãã©ããã示ãã¾ãã
keyUsages
å°åºéµã§ä½ãã§ãããã示ã Array
ã§ãã éµã®ä½¿ç¨ã¯ derivedKeyAlgorithm
ã§è¨å®ããã«ã¯ã¢ã«ã´ãªãºã ã§è¨±å¯ããã¦ããªããã°ãªããªããã¨ã«æ³¨æãã¦ãã ããã é
åã®ä½¿ç¨å¯è½ãªå¤ã¯ä»¥ä¸ã®éãã§ãã
encrypt
: ãã®éµã¯ã¡ãã»ã¼ã¸ã®æå·åã§ä½¿ç¨ãããå¯è½æ§ãããã¾ããdecrypt
: ãã®éµã¯ã¡ãã»ã¼ã¸ã®å¾©å·ã§ä½¿ç¨ãããå¯è½æ§ãããã¾ããsign
: ãã®éµã¯ã¡ãã»ã¼ã¸ã®ç½²åã§ä½¿ç¨ãããå¯è½æ§ãããã¾ããverify
: ãã®éµã¯ç½²åã®æ¤è¨¼ã§ä½¿ç¨ãããå¯è½æ§ãããã¾ããderiveKey
: ãã®éµã¯æ°ããéµã®å°åºã§ä½¿ç¨ãããå¯è½æ§ãããã¾ããderiveBits
: ãã®éµã¯ãããã®å°åºã§ä½¿ç¨ãããå¯è½æ§ãããã¾ããwrapKey
: ãã®éµã¯éµãã©ããããã®ã«ä½¿ç¨ãããå¯è½æ§ãããã¾ããunwrapKey
: ãã®éµã¯éµã®ã©ãããè§£é¤ããã®ã«ä½¿ç¨ãããå¯è½æ§ãããã¾ããCryptoKey
ã§å±¥è¡ããããããã¹ (Promise
) ã§ãã
以ä¸ã®ä¾å¤ãçºçããå ´åããããã¹ã¯æå¦ããã¾ãã
InvalidAccessError
DOMException
ãã¹ã¿ã¼éµããªã¯ã¨ã¹ããããå°åºã¢ã«ã´ãªãºã ã®éµã§ãªãå ´åãã¾ãã¯ãã®éµã® keyUsages
å¤ã« deriveKey
ãæ ¼ç´ããã¦ããªãå ´åã«çºçãã¾ãã
NotSupported
DOMException
䏿ãªã¢ã«ã´ãªãºã ãå°åºã«é©ããªãã¢ã«ã´ãªãºã ã使ç¨ãããã¨ããå ´åã ãããã¯å°åºéµã«ãªã¯ã¨ã¹ããããã¢ã«ã´ãªãºã ãéµé·ãå®ç¾©ãã¦ããªãå ´åã«çºçãã¾ãã
SyntaxError
DOMException
keyUsages
ã空ã§ãã©ããããã¦ããªãéµã®ç¨®é¡ã secret
ã¾ã㯠private
ã§ããå ´åã«çºçãã¾ãã
deriveKey()
ã対å¿ãã¦ããã¢ã«ã´ãªãºã ã¯ãããããã¾ã£ããç°ãªãç¹æ§ãæã£ã¦ãããé©ãã¦ããç¶æ³ãã¾ã£ããç°ãªãã¾ãã
HKDF ã¯éµå°åºé¢æ°ã§ãã HKDF ã¯ã ECDH éµåæå¦çã®åºåãªã©ãé«ã¨ã³ãããã¼ã®å ¥åãã éµç´ æãå°åºããããã«è¨è¨ããã¦ãã¾ãã
ãã¹ã¯ã¼ãã®ãããªç¸å¯¾çã«ã¨ã³ãããã¼ã®ä½ãå ¥åããéµãå°åºããããã«ã¯è¨è¨ããã¦ãã¾ããã PBKDF2 ã使ç¨ãã¦ãã ããã
HKDF 㯠RFC 5869 ã§å®ç¾©ããã¦ãã¾ãã
PBKDF2PBKDF2 ã¯éµå°åºé¢æ°ã§ãããã¾ãã ããã¯ããã¹ã¯ã¼ãã®ãããªç¸å¯¾çã«ã¨ã³ãããã¼ã®ä½ãå ¥åããéµç´ æãå°åºããããã«è¨è¨ããã¦ãã¾ãã PBKDF2 ã¯ãå ¥åããããã¹ã¯ã¼ãã« HMAC ã®ãããªæ©è½ã¨ã½ã«ããé©ç¨ãããã®å¦çãä½åº¦ãç¹°ãè¿ããã¨ã§éµç´ æãå°åºãã¾ãã ãã®å¦çãç¹°ãè¿ãåæ°ãå¤ããã°å¤ãã»ã©ãéµã®å°åºã«ã¯ã³ã³ãã¥ã¼ã¿ã¼ãå¿ è¦ã¨ããè¨ç®éãå¢ãã¾ããããã«ãããæ»æè ããã«ã¼ããã©ã¼ã¹ï¼ç·å½ããï¼ã使ç¨ãã¦ è¾æ¸æ»æã§éµãçºè¦ãããã¨ãé£ãããªãã¾ãã
PBKDF2 㯠RFC 2898 ã§å®ç¾©ããã¦ãã¾ãã
éµåæã¢ã«ã´ãªãºã ECDHECDH (Elliptic Curve Diffie-Hellman) ã¯éµåæã¢ã«ã´ãªãºã ã§ãã ECDH ã®å ¬ééµã¨ç§å¯éµã®ãã¢ãããããä¿æããäºäººãå ±æããç§å¯ãããªãã¡ãäºäººãå ±æããä»ã®äººã¨ã¯å ±æãããªãç§å¯ãçæãããã¨ãã§ãã¾ãã ãã®å ±æç§å¯ãå ±ééµã¨ãã¦ä½¿ç¨ãã¦éä¿¡ãå®å ¨ã«ããããï¼ä¾ãã° HKDF ã¢ã«ã´ãªãºã ã使ç¨ãã¦ï¼ãã®ãããªéµãå°åºããããã®å ¥åã¨ãã¦ä½¿ç¨ããããããã¨ãã§ãã¾ãã
ECDH 㯠RFC 6090 ã§å®ç¾©ããã¦ãã¾ãã
X25519X25519 ã¯ãECDH ã¨åæ§ã®éµåæã¢ã«ã´ãªãºã ã§ããã RFC 8032 ã§å®ç¾©ããã¦ãã Edwards-Curve ãã¸ã¿ã«ç½²åã¢ã«ã´ãªãºã ï¼EdDSAï¼ ãã¡ããªã¼ã® Curve25519 æ¥åæ²ç·ã«åºã¥ãã¦æ§ç¯ããã¦ãã¾ãã
Curve25519 ã¢ã«ã´ãªãºã ã¯æå·ã§åºã使ç¨ããã¦ãããæãå¹ççã§é«éãªã¢ã«ã´ãªãºã ã®ã²ã¨ã¤ã¨ããã¦ãã¾ãã ECDH ã§ä½¿ç¨ããã¦ãã NIST ï¼ç±³å½å½ç«æ¨æºæè¡ç ç©¶æï¼ ã®æ²ç·éµäº¤æã¢ã«ã´ãªãºã ã¨æ¯è¼ããã¨ã Curve25519 ã¯å®è£ ãç°¡åã§ãéæ¿åºæ©é¢ãéçºããã¢ã«ã´ãªãºã ã§ããããããã®è¨è¨ä¸ã®æ±ºå®äºé ãéæã§å ¬éããã¦ãã¾ãã
X25519 㯠RFC 7748 ã§å®ç¾©ããã¦ãã¾ãã
ä¾ã¡ã¢: GitHub ã®åä½ä¾ã試ãã¦ã¿ããã¨ãã§ãã¾ãã
ECDH: å ±æç§å¯éµã®å°åºãã®ä¾ã§ã¯ Alice 㨠Bob ããããã ECDH éµãã¢ãçæããå
¬ééµã交æãã¾ãã ãã㦠deriveKey()
ã使ã£ã¦å
±æ AES éµãçæããããã使ç¨ãã¦ã¡ãã»ã¼ã¸ãæå·åãã¾ãã å®å
¨ãªã³ã¼ã㯠GitHub ã§ã覧ãã ããã
/*
Derive an AES key, given:
- our ECDH private key
- their ECDH public key
*/
function deriveSecretKey(privateKey, publicKey) {
return window.crypto.subtle.deriveKey(
{
name: "ECDH",
public: publicKey,
},
privateKey,
{
name: "AES-GCM",
length: 256,
},
false,
["encrypt", "decrypt"],
);
}
async function agreeSharedSecretKey() {
// Generate 2 ECDH key pairs: one for Alice and one for Bob
// In more normal usage, they would generate their key pairs
// separately and exchange public keys securely
let aliceKeyPair = await window.crypto.subtle.generateKey(
{
name: "ECDH",
namedCurve: "P-384",
},
false,
["deriveKey"],
);
let bobKeyPair = await window.crypto.subtle.generateKey(
{
name: "ECDH",
namedCurve: "P-384",
},
false,
["deriveKey"],
);
// Alice then generates a secret key using her private key and Bob's public key.
let aliceSecretKey = await deriveSecretKey(
aliceKeyPair.privateKey,
bobKeyPair.publicKey,
);
// Bob generates the same secret key using his private key and Alice's public key.
let bobSecretKey = await deriveSecretKey(
bobKeyPair.privateKey,
aliceKeyPair.publicKey,
);
// Alice can then use her copy of the secret key to encrypt a message to Bob.
let encryptButton = document.querySelector(".ecdh .encrypt-button");
encryptButton.addEventListener("click", () => {
encrypt(aliceSecretKey);
});
// Bob can use his copy to decrypt the message.
let decryptButton = document.querySelector(".ecdh .decrypt-button");
decryptButton.addEventListener("click", () => {
decrypt(bobSecretKey);
});
}
X25519: å
±æç§å¯éµã®å°åº
ãã®ä¾ã§ã¯ã Alice 㨠Bob ã¯ãããã X25519 éµãã¢ãçæããå
¬ééµã交æãã¾ãã æ¬¡ã«ããããã deriveKey()
ã使ç¨ãã¦ãèªåèªèº«ã§çæããç§å¯éµã¨ç¸æã®å
¬ééµããå
±æã® AES éµãå°åºãã¾ãã ãã®å
±æéµã使ç¨ãã¦ã交æããã¡ãã»ã¼ã¸ãæå·åããã³å¾©å·åãããã¨ãã§ãã¾ãã
æåã«ãAlice ãéä¿¡ãããã¬ã¼ã³ããã¹ãã¡ãã»ã¼ã¸ãå
¥åããããã«ä½¿ç¨ãã HTML ã® <input>
ã¨ãæå·åããã»ã¹ãéå§ããããã«ã¯ãªãã¯ãããã¿ã³ãå®ç¾©ãã¾ãã
ããã«ç¶ãã¦ãã¢ãªã¹ãç§å¯éµã®ã³ãã¼ã§å¹³æãæå·åããå¾ã«æå·æã表示ããããã® 2 ã¤ã®è¦ç´ ãããã³ãããç§å¯éµã®ã³ãã¼ã§æå·æã復å·åããå¾ã«ããã¹ãã表示ããããã® 2 ã¤ã®è¦ç´ ãç¶ãã¾ãã
JavaScript以ä¸ã®ã³ã¼ãã¯ãderiveKey()'
ã®ä½¿ç¨æ¹æ³ã示ãã¦ãã¾ãã ãªã¢ã¼ãå´ã® X25519 å
¬ééµããã¼ã«ã«å´ã® X25519 ç§å¯éµã渡ãã¦ãå°åºãããéµã AES-GCM éµã¨ãããã¨ãæå®ãã¾ãã ã¾ããå°åºãããéµã¯æ½åºä¸å¯è½ã§ãããæå·åããã³å¾©å·åã«é©ãããã®ã«è¨å®ãã¾ãã
ãã®é¢æ°ã¯ãã³ã¼ãã®ããã«ä¸ã§ã Bob 㨠Alice ç¨ã®å ±æéµã使ããããã«ä½¿ç¨ãã¾ãã
次ã«ãAlice ãå¹³æã¡ãã»ã¼ã¸ã UTF-8 ã¨ã³ã³ã¼ããã¦ããæå·åããããã«ä½¿ç¨ãã颿°ãããã³ Bob ãã¡ãã»ã¼ã¸ã復å·ãã¦ãããã³ã¼ãããããã«ä½¿ç¨ãã颿°ãå®ç¾©ãã¾ãã ãããã®é¢æ°ã¯ããããããå ±æ AESéµãåæåãã¯ãã«ãããã³æå·åã¾ãã¯å¾©å·ããããã¹ãã弿°ã¨ãã¦åãã¾ãã
æå·åã¨å¾©å·ã«ã¯åãåæåãã¯ãã«ã使ç¨ããå¿ è¦ãããã¾ãããããã¯ç§å¯ã§ããå¿ è¦ã¯ããã¾ããããã®ãããéå¸¸ã¯æå·åãããã¡ãã»ã¼ã¸ã®æ¨ªã«ä¸¦ã¹ã¦éä¿¡ããã¾ãã ãã ãããã®ä¾ã§ã¯å®éã«ã¯ã¡ãã»ã¼ã¸ãéä¿¡ããªããããç´æ¥å©ç¨ã§ããããã«ãã¦ãã¾ãã
èªã¿è¾¼ã¿æã«ã agreeSharedSecretKey()
颿°ãå¼ã³åºããã Alice 㨠Bob ã®ãã¢ã¨å
±æéµãçæãã¾ãã ã¾ããæåã® <input>
ã§å®ç¾©ãããããã¹ãã®æå·åã¨å¾©å·ãèµ·åãã "Encrypt" ãã¿ã³ã®ã¯ãªãã¯ãã³ãã©ã¼ã追å ãã¾ãã ãã¹ã¦ã®ã³ã¼ã㯠try...catch
ãã³ãã©ã¼å
ã«ããã X25519 ã¢ã«ã´ãªãºã ã«å¯¾å¿ãã¦ããªãããã«éµã®çæã«å¤±æããå ´åã確å®ã«ãã°ã«è¨é²ã§ããããã«ãã¦ãã¾ãã
æå·å ãã¿ã³ãæ¼ãã¨ãä¸çªä¸ã® <input>
è¦ç´ ã®ããã¹ããæå·åãããæå·åãããæå·æã¨å¾©å·ãããå¹³æã次㮠2 ã¤ã®è¦ç´ ã«è¡¨ç¤ºããã¾ãã ä¸é¨ã®ãã°é åã«ã¯ãã³ã¼ãã«ãã£ã¦çæãããéµã«é¢ããæ
å ±ãæä¾ããã¾ãã
ãã®ä¾ã§ã¯ãã¦ã¼ã¶ã¼ã«ãã¹ã¯ã¼ããè¦æ±ããããã使ç¨ã㦠PBKDF2 ã使ã£ã¦ AES éµãå°åºãããã® AES éµã使ã£ã¦ã¡ãã»ã¼ã¸ãæå·åãã¾ãã å®å ¨ãªã³ã¼ã㯠GitHub ã§ã覧ãã ããã
/*
deriveKeyã¡ã½ããã®å
¥åã¨ãã¦ä½¿ç¨ããéµç´ æãåå¾ãã¾ãã
éµç´ æã¯ãã¦ã¼ã¶ã¼ããæä¾ããããã¹ã¯ã¼ãã§ãã
*/
function getKeyMaterial() {
const password = window.prompt("Enter your password");
const enc = new TextEncoder();
return window.crypto.subtle.importKey(
"raw",
enc.encode(password),
"PBKDF2",
false,
["deriveBits", "deriveKey"],
);
}
async function encrypt(plaintext, salt, iv) {
const keyMaterial = await getKeyMaterial();
const key = await window.crypto.subtle.deriveKey(
{
name: "PBKDF2",
salt,
iterations: 100000,
hash: "SHA-256",
},
keyMaterial,
{ name: "AES-GCM", length: 256 },
true,
["encrypt", "decrypt"],
);
return window.crypto.subtle.encrypt({ name: "AES-GCM", iv }, key, plaintext);
}
HKDF: å
±æã®ç§å¯ãã AES éµãå°åº
ãã®ä¾ã§ã¯ãå
±æã®ç§å¯ secret
ã使ç¨ãã¦ãã¡ãã»ã¼ã¸ plainText
ãæå·åãã¾ãããã®ç§å¯éµã¯ãECDH ãªã©ã®ã¢ã«ã´ãªãºã ã使ç¨ãã¦å°åºããã¦ããå¯è½æ§ãããã¾ãã å
±æã®ç§å¯ãç´æ¥ä½¿ç¨ãã代ããã«ã HKDF æ©è½ã®ããã®ãã¼ç´ æã¨ãã¦ä½¿ç¨ãã AES-GCM æå·å°åºãã¾ãããã®ãã¼ã使ç¨ãã¦ãã¡ãã»ã¼ã¸ãæå·åãã¾ãã GitHub ã§ã³ã¼ãã®å
¨æãã覧ãã ããã
/*
Given some key material and some random salt,
derive an AES-GCM key using HKDF.
*/
function getKey(keyMaterial, salt) {
return window.crypto.subtle.deriveKey(
{
name: "HKDF",
salt: salt,
info: new TextEncoder().encode("Encryption example"),
hash: "SHA-256",
},
keyMaterial,
{ name: "AES-GCM", length: 256 },
true,
["encrypt", "decrypt"],
);
}
async function encrypt(secret, plainText) {
const message = {
salt: window.crypto.getRandomValues(new Uint8Array(16)),
iv: window.crypto.getRandomValues(new Uint8Array(12)),
};
const key = await getKey(secret, message.salt);
message.ciphertext = await window.crypto.subtle.encrypt(
{
name: "AES-GCM",
iv: message.iv,
},
key,
plainText,
);
return message;
}
仿§æ¸ ãã©ã¦ã¶ã¼ã®äºææ§ é¢é£æ
å ±
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4