Skip to content

Instantly share code, notes, and snippets.

@bshambaugh
Created September 23, 2022 23:35
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save bshambaugh/427bb7e41fbe3f0169745fd3e821c2a5 to your computer and use it in GitHub Desktop.
This does not produce the correct signature
/// replicating section: A.3. Example JWS Using ECDSA P-256 SHA-256 [https://www.rfc-editor.org/rfc/rfc7515#appendix-A.3]
/// seeAlso: [https://www.rfc-editor.org/rfc/rfc7518#section-3.4]
var EC = require('elliptic').ec;
var secp256r1 = new EC('p256');
var sha256 = require('@stablelib/sha256')
var u8a = require('uint8arrays')
var HMAC = require("@stablelib/hmac").HMAC
var SHA256 = require("@stablelib/sha256").SHA256
var sjcl = require('sjcl')
// const header = '{\"typ\":\"JWT\"\,\"alg\":\"ES256\"\}'
const header = '{\"alg\":\"ES256\"}'
const Eightbit = u8a.fromString(header)
const base64 = u8a.toString(Eightbit,'base64url')
console.log(header)
console.log(Eightbit)
console.log(base64)
console.log("")
// const payload = '{\"iss\":\"joe\",\"exp\":1300819380,\"http://example.com/is_root\":true}'
const payload = '{\"iss\":\"joe\",\"exp\":1300819380,\"http://example.com/is_root\":true}'
const EightbitPayload = u8a.fromString(payload)
const base64Payload = u8a.toString(EightbitPayload,'base64url')
const signingInput = base64+'.'+base64Payload
const u8aSigningInput = u8a.fromString(signingInput)
console.log(payload)
console.log(EightbitPayload)
console.log(base64Payload)
console.log("")
console.log(u8aSigningInput)
// sign with this JWK
/*
{"kty":"EC",
"crv":"P-256",
"x":"f83OJ3D2xF1Bg8vub9tLe1gHMzV76e8Tus9uPHvRVEU",
"y":"x_FEzRu9m36HLN_tue659LNpXW6pCyStikYjKIWI5a0",
"d":"jpsQnnGQmL-YBIffH1136cspYG6-0iY7X1fCE9-E9LI"
}
*/
const base64urlx = "f83OJ3D2xF1Bg8vub9tLe1gHMzV76e8Tus9uPHvRVEU"
const base64urly = "x_FEzRu9m36HLN_tue659LNpXW6pCyStikYjKIWI5a0"
const base64urld = "jpsQnnGQmL-YBIffH1136cspYG6-0iY7X1fCE9-E9LI"
const x = u8a.toString(u8a.fromString(base64urlx,'base64url'),'base16')
console.log(x)
const y = u8a.toString(u8a.fromString(base64urly,'base64url'),'base16')
console.log(y)
const privateKey = u8a.toString(u8a.fromString(base64urld,'base64url'),'base16')
console.log(privateKey)
const publicKey = x+y
console.log('PublicKey from base64url')
console.log(publicKey)
//const privateKey = '7af6732f581d005afcf216f6385ff6371029242cc60840dd7d2a7a5503b7d21'
const keyPair = secp256r1.keyFromPrivate(privateKey,'hex')
const pk = keyPair.getPublic('hex')
console.log('PublicKey from private')
console.log(pk)
/*
const myBitArray = sjcl.hash.sha256.hash(signingInput)
const hashedMsg = sjcl.codec.hex.fromBits(myBitArray)
*/
const hashedMsg = sha256.hash(u8aSigningInput)
console.log('the hashed message is')
console.log(hashedMsg)
// the hashing algorithm looks healthy...
// what about the signature? it looks fishy....
const {r, s } = keyPair.sign(hashedMsg)
//const newR = leftpad(r.toString('hex'))
//const newY = leftpad(s.toString('hex'))
const signature = keyPair.sign(hashedMsg)
/*
const signatureR = (signature.r).toString('hex')
console.log(u8a.fromString(signatureR,'base16'))
*/
//console.log(signature)
const signatureHex = leftpad((signature.r).toString('hex')) + leftpad((signature.s).toString('hex'))
//const signatureHex = newR + newY
//console.log(signatureHex)
u8aSig = u8a.fromString(signatureHex)
b64Sig = u8a.toString(u8aSig,'base64url')
//console.log(b64Sig)
//console.log(keyPair.verify(hashedMsg, signature))
console.log(signingInput+'.'+b64Sig)
// Verify signature
//console.log(keyPair.verify(hashedMsg, signature));
// from the did-jwt library:::
function leftpad(data, size = 64) {
if (data.length === size) return data
return '0'.repeat(size - data.length) + data
}
@bshambaugh
Copy link
Author

bshambaugh commented Sep 23, 2022

output from code:

~/Downloads/JWK_and_x509/createJWK$ node combined3.js 
{"alg":"ES256"}
Uint8Array(15) [
  123, 34,  97, 108, 103, 34,
   58, 34,  69,  83,  50, 53,
   54, 34, 125
]
eyJhbGciOiJFUzI1NiJ9

{"iss":"joe","exp":1300819380,"http://example.com/is_root":true}
Uint8Array(64) [
  123,  34, 105, 115, 115,  34,  58,  34, 106, 111, 101,
   34,  44,  34, 101, 120, 112,  34,  58,  49,  51,  48,
   48,  56,  49,  57,  51,  56,  48,  44,  34, 104, 116,
  116, 112,  58,  47,  47, 101, 120,  97, 109, 112, 108,
  101,  46,  99, 111, 109,  47, 105, 115,  95, 114, 111,
  111, 116,  34,  58, 116, 114, 117, 101, 125
]
eyJpc3MiOiJqb2UiLCJleHAiOjEzMDA4MTkzODAsImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ

Uint8Array(107) [
  101, 121,  74, 104,  98,  71,  99, 105,  79, 105,  74, 70,
   85, 122,  73,  49,  78, 105,  74,  57,  46, 101, 121, 74,
  112,  99,  51,  77, 105,  79, 105,  74, 113,  98,  50, 85,
  105,  76,  67,  74, 108, 101,  72,  65, 105,  79, 106, 69,
  122,  77,  68,  65,  52,  77,  84, 107, 122,  79,  68, 65,
  115,  73, 109, 104,  48, 100,  72,  65,  54,  76, 121, 57,
  108, 101,  71,  70, 116,  99,  71, 120, 108,  76, 109, 78,
  118,  98,  83,  57, 112,  99,  49,  57, 121,  98,  50, 57,
   48,  73, 106, 112,
  ... 7 more items
]
7fcdce2770f6c45d4183cbee6fdb4b7b580733357be9ef13bacf6e3c7bd15445
c7f144cd1bbd9b7e872cdfedb9eeb9f4b3695d6ea90b24ad8a4623288588e5ad
8e9b109e719098bf980487df1f5d77e9cb29606ebed2263b5f57c213df84f4b2
PublicKey from base64url
7fcdce2770f6c45d4183cbee6fdb4b7b580733357be9ef13bacf6e3c7bd15445c7f144cd1bbd9b7e872cdfedb9eeb9f4b3695d6ea90b24ad8a4623288588e5ad
PublicKey from private
047fcdce2770f6c45d4183cbee6fdb4b7b580733357be9ef13bacf6e3c7bd15445c7f144cd1bbd9b7e872cdfedb9eeb9f4b3695d6ea90b24ad8a4623288588e5ad
the hashed message is
Uint8Array(32) [
  180,  18, 240, 220, 249,   3,  49, 190,
  173, 106, 190, 219,  46, 253, 149, 129,
  253, 214, 109,  21,  89,  79,  24,  93,
  153, 224, 231,  84, 182,  63, 136, 232
]
eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJqb2UiLCJleHAiOjEzMDA4MTkzODAsImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ.ZTE3NDllMjZjNTAzMmUxNjYyYjA1ZWQ1ODcxZWUyNjA4ZmVhZjcxZWRhZGNjOTNjZmIwYjIzZmEzYTVmZGZkMGQxN2JlNmMzMTJkZmIwZWQ0OTRkZDcxYzFmYTYyYTJlYmE4MWFjYjIwMjRhMDEzZjQ2YzA0NzhlNDYzY2VlMjI

@bshambaugh
Copy link
Author

bshambaugh commented Sep 23, 2022

Output that I get:
eyJhbGciOiJFUzI1NiJ9.
eyJpc3MiOiJqb2UiLCJleHAiOjEzMDA4MTkzODAsImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ.
ZTE3NDllMjZjNTAzMmUxNjYyYjA1ZWQ1ODcxZWUyNjA4ZmVhZjcxZWRhZGNjOTNjZmIwYjIzZmEzYTVmZGZkMGQxN2JlNmMzMTJkZmIwZWQ0OTRkZDcxYzFmYTYyYTJlYmE4MWFjYjIwMjRhMDEzZjQ2YzA0NzhlNDYzY2VlMjI

Output claimed in Appendix A.3 in RFC 7515
eyJhbGciOiJFUzI1NiJ9.
eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFt
cGxlLmNvbS9pc19yb290Ijp0cnVlfQ.
DtEhU3ljbEg8L38VWAfUAqOyKAM6-Xx-F4GawxaepmXFCgfTjDxw5djxLa8ISlSA
pmWQxfKTUJqPP3-Kg6NU1Q

@chongkan
Copy link

  1. Copy the gist into an index.js file
  2. Copy the following code into a package.json file
  3. % npm install
  4. % npm start
{
  "name": "Example JWS Using ECDSA P-256 SHA-256",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "start": "node index.js",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "@stablelib/hmac": "^1.0.1",
    "@stablelib/sha256": "^1.0.1",
    "base64url-universal": "^2.0.0",
    "elliptic": "^6.5.4",
    "sjcl": "^1.0.8",
    "uint8arrays": "^3.1.0"
  }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment