javascript - სიმეტრიული გასაღების საჯარო RSA გასაღებით გარშემორტყმა იწვევს DOMException (InvalidAccessError)


მე ასევე ვცდილობ სიმეტრიული გასაღების გახვეული ფორმით გამოყენებას Web Crypto API-ის გამოყენებით, მაგრამ მე მივიღე შეცდომა: DOMException: key.usages არ იძლევა ამ ოპერაციის ჩატარების საშუალებას

სიმართლე გითხრათ, ვებ-კრიპტოს API-ის გამოყენებაში ჯერ კიდევ ძალიან ახალი ვარ, ამიტომ სრულად ვერ ვხვდები, რატომ არის ეს პრობლემა. მინდა სიმმეტრიული გასაღების პაკეტი საჯარო გასაღეთთან დავაფარე და მოგვიანებით გავაღო ჩემი კერძო გასაღით.

მე პრობლემას გამოვყავი პატარა კოდის სენდბოქსიმში https://codesandbox.io/s/cranky-driscoll-v0itr?file=/src/index.ts

ანალოგიურად, პრობლემის განმეორებაზე შემდეგი ნაბიჯები შეიძლება გამოყენებულ იქნას.

  • გენერირება კრიპტოკეის წყვილი (აქ მე ვიყენე RSA)

  • გაწარმოე სიმეტრიული კლავიში

  • ზარის ჩატარება

    window.crypto.subtle.wrapKey(
        "raw",
        fileKey,
        publicKey,
        publicKey.algorithm.name
    );
    

აქაა სრული კოდი სენდბოქსიდან:

sync function foo() {
  try {
    const cryptoKeyPair = await window.crypto.subtle.generateKey(
      {
        name: "RSA-OAEP",
        modulusLength: 4096,
        publicExponent: new Uint8Array([1, 0, 1]),
        hash: "SHA-256"
      },
      true,
      ["encrypt", "decrypt"]
    );
    const publicKey = cryptoKeyPair.publicKey;

    const fileKey = await window.crypto.subtle.generateKey(
      { name: "AES-GCM", length: 256 },
      true,
      ["encrypt", "decrypt"]
    );

    const wrapKeyResult = await window.crypto.subtle.wrapKey(
      "raw",
      fileKey,
      publicKey,
      publicKey.algorithm.name
    );
    // ^^ here we get error: DOMException: key.usages does not permit this operation
    /** 
    * {
    *  code: 15
    *  message: "key.usages does not permit this operation"
    *  name: "InvalidAccessError"
    * }
    */
    console.log("Wrapped Key", wrapKeyResult);
  } catch (error) {
    console.error("something went wrong", error);
    throw error; 
}

foo()
  .then((res) => {
    console.log("I succeeded!");
  })
  .catch((error) => console.log("I failed with ", error));

პასუხი #1

generateKey()-ში გამოყენებულია არასწორი საკეტის გამოყენების მეთოდები. სწორი იქნება wrapKey და unwrapKey, რადგან RSA საკეტის წყვილი გამოიყენება სიმეტრიული AES-GCM საკეტის ჩამორთმევისთვის/შეცვლისთვის:

async function foo() {
    try {
        const cryptoKeyPair = await window.crypto.subtle.generateKey(
            {
                name: "RSA-OAEP",
                modulusLength: 4096,
                publicExponent: new Uint8Array([1, 0, 1]),
                hash: "SHA-256"
            },
            true,
            ["wrapKey", "unwrapKey"]                      // Apply wrapKey and unwrapKey here! 
        );
        const publicKey = cryptoKeyPair.publicKey;

        const fileKey = await window.crypto.subtle.generateKey(
            { name: "AES-GCM", length: 256 },
            true,
            ["encrypt", "decrypt"]
        );

        const wrapKeyResult = await window.crypto.subtle.wrapKey(
            "raw",
            fileKey,
            publicKey,
            publicKey.algorithm.name
        );
        console.log("Wrapped Key", new Uint8Array(wrapKeyResult));
  
    } catch (error) {
        console.error("something went wrong", error);
        throw error;
    }
}

foo()
    .then((res) => {
        console.log("I succeeded!");
    })
    .catch((error) => console.log("I failed with ", error));