diff --git a/.gitignore b/.gitignore index 7e446a4..ce6672d 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,4 @@ config/self-description-ignore config/example.env output/old old.json +.idea diff --git a/config/example.env b/config/example.env index 8dd801c..0599023 100644 --- a/config/example.env +++ b/config/example.env @@ -1,3 +1,4 @@ +SIGNATURE_ALGORITHM="PS256" PRIVATE_KEY="-----BEGIN PRIVATE KEY----- MIIcFFm9234923kMqkcaj3mfX1xWxKeJb... ... @@ -12,4 +13,4 @@ VERIFICATION_METHOD="did:web:delta-dao.com#X509" X5U_URL="https://delta-dao.com/.well-known/x509CertificateChain.pem" API_VERSION="2206" BASE_URL="https://compliance.gaia-x.eu" -CONTROLLER="did:web:delta-dao.com" \ No newline at end of file +CONTROLLER="did:web:delta-dao.com" diff --git a/index.js b/index.js index a2323ac..e3022f4 100644 --- a/index.js +++ b/index.js @@ -36,53 +36,109 @@ function sha256(input) { } async function sign(hash) { - const algorithm = 'PS256' - const rsaPrivateKey = await jose.importPKCS8( + + /* + Key type: Public / Private key pairs (RSA, EC, OKP) + Algorithms: + RSA signature with PKCS #1 and SHA-2: RS256, RS384, RS512 + RSA PSS signature with SHA-2: PS256, PS384, PS512 + ECDSA signature with SHA-2: ES256, ES256K, ES384, ES512 + Edwards-curve DSA: EdDSA + */ + console.log("Signing privateKey") + + // JSON Web Key (JWK ). “RSA”, “EC”, “OKP”, and “oct” key types are supported. + const privateKey = await jose.importPKCS8( process.env.PRIVATE_KEY, - algorithm + process.env.SIGNATURE_ALGORITHM ) - try { - const jws = await new jose.CompactSign(new TextEncoder().encode(hash)) - .setProtectedHeader({ alg: 'PS256', b64: false, crit: ['b64'] }) - .sign(rsaPrivateKey) + if (process.env.SIGNATURE_ALGORITHM === "PS256") { + console.log("Using PS256") + try { + // This supports RSA keys only + const jws = await new jose.CompactSign(new TextEncoder().encode(hash)) + .setProtectedHeader({alg: 'PS256', b64: false, crit: ['b64']}) + .sign(privateKey) + console.log("Finished signing") + return jws + } catch (error) { + console.log(error) + } - return jws - } catch (error) { - console.error(error) + } + else if (process.env.SIGNATURE_ALGORITHM === "ES256") { + console.log("Using ES256") + try { + const jws = await new jose.SignJWT({ 'urn:example:claim': true }) + .setProtectedHeader({ alg: 'ES256' }) + .sign(privateKey) + console.log("Finished signing") + return jws + } catch (error) { + console.log(error) + } + } + else { + message = "Unsupported SIGNATURE_ALGORITHM" + process.env.SIGNATURE_ALGORITHM + ". Exiting!" + console.log(message) + throw new Error(message) } } async function createProof(hash) { + console.log("Creating proof") const proof = { type: 'JsonWebSignature2020', created: new Date(CURRENT_TIME).toISOString(), proofPurpose: 'assertionMethod', verificationMethod: process.env.VERIFICATION_METHOD ?? 'did:web:compliance.lab.gaia-x.eu', - jws: await sign(hash), + jws: await sign(hash) } - + console.log("Finished proof") return proof } -async function verify(jws) { - const algorithm = 'PS256' +async function verify(jwt) { + const algorithm = process.env.SIGNATURE_ALGORITHM const x509 = await jose.importX509(process.env.CERTIFICATE, algorithm) const publicKeyJwk = await jose.exportJWK(x509) + const pubkey = await jose.importJWK(publicKeyJwk, process.env.SIGNATURE_ALGORITHM) + + if (process.env.SIGNATURE_ALGORITHM === "PS256") { + jws = jwt.jws.replace('..', `.${hash}.`) + console.log("Using PS256") + try { + const result = await jose.compactVerify(jws, pubkey) + return { + protectedHeader: result.protectedHeader, + content: new TextDecoder().decode(result.payload), + } + } catch (error) { + console.error("PS256 verification failed: " + error) + } - const pubkey = await jose.importJWK(publicKeyJwk, 'PS256') - - try { - const result = await jose.compactVerify(jws, pubkey) - - return { - protectedHeader: result.protectedHeader, - content: new TextDecoder().decode(result.payload), + } + else if (process.env.SIGNATURE_ALGORITHM === "ES256") { + console.log("Using ES256") + console.log(jwt) + try { + + const { payload, protectedHeader } = await jose.jwtVerify(jwt.jws, pubkey) + + console.log(payload) + console.log(protectedHeader) + return { + protectedHeader: protectedHeader, + payload: payload, + content: payload + } + } catch (error) { + console.error("ES256 verification failed: " + error) } - } catch (error) { - return {} } + return {} } async function createSignedSdFile(selfDescription, proof) { @@ -177,9 +233,8 @@ async function main() { : '❌ SD signing failed (local)' ) - const verificationResult = await verify( - proof.jws.replace('..', `.${hash}.`) - ) + const verificationResult = await verify(proof) + console.log(verificationResult) logger( verificationResult?.content === hash ? '✅ Verification successful (local)' diff --git a/package-lock.json b/package-lock.json index f84049a..d97e4bb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,7 @@ "dependencies": { "axios": "^0.27.2", "dotenv": "^16.0.1", - "jose": "^4.8.1" + "jose": "^4.10.3" } }, "node_modules/asynckit": { @@ -88,9 +88,9 @@ } }, "node_modules/jose": { - "version": "4.8.1", - "resolved": "https://registry.npmjs.org/jose/-/jose-4.8.1.tgz", - "integrity": "sha512-+/hpTbRcCw9YC0TOfN1W47pej4a9lRmltdOVdRLz5FP5UvUq3CenhXjQK7u/8NdMIIShMXYAh9VLPhc7TjhvFw==", + "version": "4.10.3", + "resolved": "https://registry.npmjs.org/jose/-/jose-4.10.3.tgz", + "integrity": "sha512-3S4wQnaoJKSAx9uHSoyf8B/lxjs1qCntHWL6wNFszJazo+FtWe+qD0zVfY0BlqJ5HHK4jcnM98k3BQzVLbzE4g==", "funding": { "url": "https://github.com/sponsors/panva" } @@ -164,9 +164,9 @@ } }, "jose": { - "version": "4.8.1", - "resolved": "https://registry.npmjs.org/jose/-/jose-4.8.1.tgz", - "integrity": "sha512-+/hpTbRcCw9YC0TOfN1W47pej4a9lRmltdOVdRLz5FP5UvUq3CenhXjQK7u/8NdMIIShMXYAh9VLPhc7TjhvFw==" + "version": "4.10.3", + "resolved": "https://registry.npmjs.org/jose/-/jose-4.10.3.tgz", + "integrity": "sha512-3S4wQnaoJKSAx9uHSoyf8B/lxjs1qCntHWL6wNFszJazo+FtWe+qD0zVfY0BlqJ5HHK4jcnM98k3BQzVLbzE4g==" }, "mime-db": { "version": "1.52.0", diff --git a/package.json b/package.json index 20dc0ce..bcd5e25 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,6 @@ "dependencies": { "axios": "^0.27.2", "dotenv": "^16.0.1", - "jose": "^4.8.1" + "jose": "^4.10.3" } }