2017-12-30 28 views
3

私はWeb暗号化APIで生成されたRSA秘密キーをパスワードで保護しようとしていました。これを行うには、私が最初に AESキーでRSA秘密キーをラップしてアンラッピングする

  • RSA鍵ペアを生成

    1. は、その後、私はその後、私はSTEP2からAESキーでSTEP1からのRSA秘密鍵をラップするパスワード
    2. からAES対称鍵を導出します。
    3. 私は終わりだとき、私はすぐに私はそれを

    のラップを解除しようとunwrap方法にこれらのすべてを渡すことで、これは働いていた検証しようとするここでは、コードです:

    <html> 
    <script> 
    function wrap(password) { 
        var iterations = 1000000; 
    
        // Utility function 
        var stringToByteArray = function(s){ 
        if ("TextEncoder" in window) { 
         encoder = new window.TextEncoder; 
         return encoder.encode(s); 
        } 
        var result = new Uint8Array(s.length); 
        for (var i=0; i<s.length; i++){ 
         result[i] = s.charCodeAt(i); 
        } 
        return result; 
        } 
    
        var saltBytes = stringToByteArray("NaCl"); 
        var passphraseBytes = stringToByteArray(password); 
    
        return crypto.subtle.generateKey({ 
        name: "RSA-OAEP", 
        modulusLength: 2048, 
        publicExponent: new Uint8Array([1, 0, 1]), 
        hash: {name: "SHA-256"} 
        }, true, ["encrypt", "decrypt"]).then(function(keyPair) { 
        return crypto.subtle.importKey(
         "raw", passphraseBytes, {name: "PBKDF2"}, false, ["deriveKey"] 
        ).then(function(baseKey) { 
         return window.crypto.subtle.deriveKey(
         {name: "PBKDF2", salt: saltBytes, iterations: iterations, hash: "SHA-1"}, 
         baseKey, 
         {name: "AES-CBC", length: 256}, 
         false, 
         ["encrypt", "decrypt", "wrapKey", "unwrapKey"] 
        ).then(function(wrapperKey) { 
         var iv = crypto.getRandomValues(new Uint8Array(16)); 
         return crypto.subtle.wrapKey(
          "pkcs8", 
          keyPair.privateKey, 
          wrapperKey, 
          {name: "AES-CBC", iv: iv } 
         ).then(function(wrappedKey) { 
          return { 
          iv: iv, 
          wrapper: wrapperKey, 
          wrapped: wrappedKey 
          } 
         }) 
         }); 
        }).catch(function(err) { 
         console.log(err); 
        }); 
        }) 
    } 
    
    
    function unwrap(account) { 
        console.log(account); 
        crypto.subtle.unwrapKey(
        "pkcs8", 
        account.wrapped, 
        account.wrapper, 
        { 
         name: "AES-CBC", 
         iv: account.iv 
        }, 
        { 
         name: "RSA-OAEP", 
         modulusLength: 2048, 
         publicExponent: new Uint8Array([1, 0, 1]), 
         hash: {name: "SHA-256"} 
        }, 
        true, 
        ['decrypt', 'encrypt'] 
    ).then(function(privateKey) { 
        console.log("unwrapped = ", privateKey); 
        }).catch(function(e) { 
        console.log(e) 
        }) 
    } 
    
    // Finally I call "wrap" and then "unwrap" 
    wrap("password").then(unwrap) 
    
    </script> 
    </html> 
    

    しかし、コードは動作しません。ラッピングコードはエラーを投げず、キーが生成されているようです(ただし、これらが有効かどうかはわかりませんが)。私はunwrapKeyメソッドを実行しようとする。しかし、私は次のエラーを取得する:私はこの仕事を得ることができないので

    DOMException: Cannot create a key using the specified key usages. 
    

    私は、最後の24時間の私の髪を引っ張ってきました。誰も問題を見つけることができますか?これは完璧に自己完結型のコードなので、コピーしてHTMLファイルに貼り付けてブラウザで開くことで試してみることができます。

  • 答えて

    0

    公開鍵/秘密鍵を対称鍵でラップすることは、ラップ/アンラップの動作方法ではありません。

    • wrapKey , allowing the key to wrap a symmetric key for usage (transfer, storage) in unsecure environments.
    • unwrapKey , allowing the key to unwrap a symmetric key for usage (transfer, storage) in unsecure environments.

    あなたは、対称鍵をアンラップ/ラップすることができますが、ラップ/アンラップおそらくラップされた鍵は、対称鍵と非対称ではないことを期待するので、あなたは、公開鍵/秘密鍵のペア(またはキー)をアンラップ/ラップすることはできませんキー。

    The SubtleCrypto.wrapKey() method returns a Promise of a wrapped symmetric key for usage (transfer, storage) in unsecure environments. The wrapped buffer returned is in the format given in parameters, and contained the key wrapped by the give wrapping key with the given algorithm.

    The SubtleCrypto.unwrapKey() method returns a Promise of a CryptoKey corresponding to the wrapped key given in parameter.

    +1

    あなたがMozillaのドキュメントに基づいて話している場合は、私は彼らのドキュメントが不完全で、時にはWebCrypto APIの少なくとも誤解であることを学んだので、それはWebCryptoのAPIに来るとき、私は彼らを信用していません。元のW3Cの提案にはそのような制限はなく、仕様によれば、それは単なる暗号化メカニズムだという。また、私はこの質問をして以来、私はこれを行うライブラリを見つけたhttps://github.com/safebash/OpenCrypto – Vlad

    +0

    確かにそれはMozillaのドキュメントであり、確かにほとんどの(すべて?)現在の主要なブラウザの状態です。また、W3Cは、あなたが言うように、ラッピングを制限しません。しかし、上記は開発者向けのbroswer APIを通じて利用できるものです。あなたの要件を実装するソリューションが見つかりました。すべて:MBCの悪い実装...(メジャーブラウザーコンソーシアム)...新年あけましておめでとうございます! –

    関連する問題