GithubHelp home page GithubHelp logo

Comments (7)

jonasfj avatar jonasfj commented on May 22, 2024 1

I don't find it hard to believe that there are other libraries out there that'll accept JWKs that are somewhat malformed.

I'm guessing that you could simply remove the padding and possibly prepend the y member with zeros. But the fact that the y member has the wrong length, should probably be a warning flag -- maybe there is something wrong with the key.

In any case, unless we can somehow reasonably say that the input is a valid JWK and would be accepted by most other webcrypto implementations, then I suggest we close this issue.

from webcrypto.dart.

leanhdaoit avatar leanhdaoit commented on May 22, 2024

cc @jonasfj 🙏

from webcrypto.dart.

jonasfj avatar jonasfj commented on May 22, 2024

What happens if you do this in a various browsers?

window.crypto.subtle.importKey(
  'jwk', {
    "kty": "EC",
    "crv": "P-256",
    "x": "h0rbX_vxGVgx-u-ITxnydyy7W9VNGFITcqltL7hDa5A=",
    "y": "iQdcRQ8aghMIKnnE1RZEzrfag4c2PHBq8kVea6tK6w==",
    "d": "A-zAYOf8KYYxZvP6akkL6SNjBPygstC7VALP2cuh0QA="
  }, {
    "name": "ECDH",
     "namedCurve": "P-256"
  }, true, ['deriveKey']
).then(
  k => console.log(k)
).catch(
  err => console.log(err)
);

Fails for me on both Chrome and Firefox.


This indicates to me that the JWK might be malformed or incorrectly formatted.

from webcrypto.dart.

jonasfj avatar jonasfj commented on May 22, 2024

BASE64URL(OCTETS) denotes the base64url encoding of OCTETS, per
Section 2 of [JWS].

From: https://datatracker.ietf.org/doc/html/rfc7517#section-1.1

Base64url Encoding
Base64 encoding using the URL- and filename-safe character set
defined in Section 5 of RFC 4648 [RFC4648], with all trailing '='
characters omitted (as permitted by Section 3.2) and without the
inclusion of any line breaks, whitespace, or other additional
characters. Note that the base64url encoding of the empty octet
sequence is the empty string. (See Appendix C for notes on
implementing base64url encoding without padding.)

From: https://www.rfc-editor.org/rfc/rfc7515.html#section-2

from webcrypto.dart.

jonasfj avatar jonasfj commented on May 22, 2024

Is there any reason to think this is a valid JWK? What other libraries that understand JWKs will accept this JWK?

from webcrypto.dart.

leanhdaoit avatar leanhdaoit commented on May 22, 2024

What happens if you do this in a various browsers?

window.crypto.subtle.importKey(
  'jwk', {
    "kty": "EC",
    "crv": "P-256",
    "x": "h0rbX_vxGVgx-u-ITxnydyy7W9VNGFITcqltL7hDa5A=",
    "y": "iQdcRQ8aghMIKnnE1RZEzrfag4c2PHBq8kVea6tK6w==",
    "d": "A-zAYOf8KYYxZvP6akkL6SNjBPygstC7VALP2cuh0QA="
  }, {
    "name": "ECDH",
     "namedCurve": "P-256"
  }, true, ['deriveKey']
).then(
  k => console.log(k)
).catch(
  err => console.log(err)
);

Fails for me on both Chrome and Firefox.

This indicates to me that the JWK might be malformed or incorrectly formatted.

I also fail on Chrome with error DOMException: The JWK member "x" could not be base64url decoded or contained padding. If remove = in x, y, d it's will show DOMException: The JWK's "y" member defines an octet string of length 31 bytes but should be 32.
But when i run it on node js with library packages below it works fine.

Here is my example project: https://github.com/leanhdaoit/chat-e2e-example
Logs of example:

===========Import key by old @peculiar/webcrypto=============
jwk: {"kty":"EC","crv":"P-256","x":"h0rbX_vxGVgx-u-ITxnydyy7W9VNGFITcqltL7hDa5A","y":"iQdcRQ8aghMIKnnE1RZEzrfag4c2PHBq8kVea6tK6w","d":"A-zAYOf8KYYxZvP6akkL6SNjBPygstC7VALP2cuh0QA"}
privateKey:[object CryptoKey]
===========Import key by old webcrypto=============
jwk: {"kty":"EC","crv":"P-256","x":"h0rbX_vxGVgx-u-ITxnydyy7W9VNGFITcqltL7hDa5A","y":"iQdcRQ8aghMIKnnE1RZEzrfag4c2PHBq8kVea6tK6w","d":"A-zAYOf8KYYxZvP6akkL6SNjBPygstC7VALP2cuh0QA"}
privateKey:[object Object]

maybe the old libraries don't check the format of the x and y points, but it can still do deriveKey and encrypt/decrypt (AES-GCM) 🤔🤔

from webcrypto.dart.

leanhdaoit avatar leanhdaoit commented on May 22, 2024

I can confirm that after padLeft zero with length 32 of y it works fine.
Code Example:

import 'package:webcrypto/webcrypto.dart';
import 'package:elliptic/elliptic.dart' as elliptic;

  Map<String, String> convertPrivateKeyHexToJWK(String privateKeyHex) {
    final privateKeyEC = convertPrivateKeyHexToEC(privateKeyHex);
    final encodedX = encodeBigInt(privateKeyEC.publicKey.X);
    final encodedXPadLeft = padLeft(encodedX, 32, 0);
    final encodedY = encodeBigInt(privateKeyEC.publicKey.Y);
    final encodedYPadLeft = padLeft(encodedY, 32, 0);
    final encodedD = encodeBigInt(privateKeyEC.D);
    final encodedDPadLeft = padLeft(encodedD, 32, 0);
    final privateKeyJWK = {
      'kty': 'EC',
      'crv': 'P-256',
      'x': base64UrlEncode(encodedXPadLeft),
      'y': base64UrlEncode(encodedYPadLeft),
      'd': base64UrlEncode(encodedDPadLeft)
    };
    return privateKeyJWK;
  }
  
  elliptic.PrivateKey convertPrivateKeyHexToEC(String privateKeyHex) =>
      elliptic.PrivateKey.fromHex(elliptic.getP256(), privateKeyHex);
      
  Uint8List encodeBigInt(BigInt number) {
    final _byteMask = BigInt.from(0xff);
    final size = (number.bitLength + 7) >> 3;
    final result = new Uint8List(size);
    for (int i = 0; i < size; i++) {
      result[size - i - 1] = (number & _byteMask).toInt();
      number = number >> 8;
    }
    return result;
  }
  
  Uint8List padLeft(
      Uint8List input, int desiredLength, int paddingValue) {
    if (input.length >= desiredLength) {
      return input;
    } else {
      var padding = Uint8List(desiredLength - input.length);
      padding.fillRange(0, padding.length, paddingValue);
      return Uint8List.fromList([...padding, ...input]);
    }
  }

from webcrypto.dart.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.