Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

EcdsaSecp256k1RecoverySignature2020 for commit credentials #275

Merged
merged 5 commits into from
Nov 30, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ cljs-node-test: node_modules package-lock.json
npx shadow-cljs release node-test

nodejs-test: out/flureenjs.js
cd test/nodejs && npm install && npm test
cd test/nodejs && npm install && node --experimental-vm-modules node_modules/jest/bin/jest.js

browser-test: out/flureedb.js
cd test/browser && npm install && npm ci
Expand Down
2 changes: 1 addition & 1 deletion deps.edn
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
cheshire/cheshire {:mvn/version "5.11.0"}
instaparse/instaparse {:mvn/version "1.4.12"}
com.fluree/json-ld {:git/url "https://github.com/fluree/json-ld.git"
:sha "edb189ce94282b1ea27fd04bb999c91f1492bf4b"}
:sha "2e69362f611def8cc6793c6ddf24e4671fb6f397"}

;; logging
org.clojure/tools.logging {:mvn/version "1.2.4"}
Expand Down
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@
"bufferutil": "^4.0.7",
"form-data": "^4.0.0",
"js-sha3": "^0.8.0",
"jsonld": "^8.1.0",
"scrypt-js": "^3.0.1",
"seedrandom": "^3.0.5",
"source-map-support": "^0.5.21",
"utf-8-validate": "^5.0.10",
"ws": "^8.8.0",
"seedrandom": "^3.0.5"
"ws": "^8.8.0"
},
"browser": {
"ws": false
Expand Down
2 changes: 1 addition & 1 deletion src/deps.cljs
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
;; This file is auto-generated by target-bundle-libs. DO NOT EDIT!

{:npm-deps {"bufferutil" "^4.0.7", "utf-8-validate" "^5.0.10", "axios" "^0.27.2", "@cljs-oss/module-deps" "^1.1.1", "seedrandom" "^3.0.5", "source-map-support" "^0.5.21", "js-sha3" "^0.8.0", "scrypt-js" "^3.0.1", "ws" "^8.8.0", "form-data" "^4.0.0", "@fluree/sjcl" "^1.0.8-3"}}
{:npm-deps {"bufferutil" "^4.0.7", "utf-8-validate" "^5.0.10", "axios" "^0.27.2", "jsonld" "^8.1.0", "@cljs-oss/module-deps" "^1.1.1", "seedrandom" "^3.0.5", "source-map-support" "^0.5.21", "js-sha3" "^0.8.0", "scrypt-js" "^3.0.1", "ws" "^8.8.0", "form-data" "^4.0.0", "@fluree/sjcl" "^1.0.8-3"}}
43 changes: 41 additions & 2 deletions src/fluree/db/did.cljc
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
(ns fluree.db.did
(:require [fluree.crypto :as crypto]))
(:require [fluree.crypto :as crypto]
[alphabase.core :as alphabase]
[alphabase.base58 :as base58]
[clojure.string :as str]))

;; did operations

Expand Down Expand Up @@ -28,4 +31,40 @@
(let [public (crypto/pub-key-from-private private-key)
auth-id (crypto/account-id-from-public public)
did-id (auth-id->did auth-id)]
(did-map did-id public private-key)))
(did-map did-id public private-key)))

;; https://github.com/multiformats/multicodec/blob/master/table.csv
(def secp256k1-pub
"The multicodec prefix for a secp256k1 public key."
"e7")

(defn encode-did-key
"Encodes a secp256k1 public key as a base58 multibase did:key."
[pubkey]
(let [pubkey-header secp256k1-pub]
(str "did:key:z" (base58/encode (alphabase/hex->bytes (str pubkey-header pubkey))))))

;; https://github.com/multiformats/multibase/blob/master/multibase.csv
(def base58btc
"The multibase prefix for a base58btc encoded string."
"z")

(defn decode-did-key
"Return the hex encoded public key from a did:key, or nil if it is not a properly
encoded secp256k1 public key."
[did]
(let [[_ _ multibase-value] (str/split did #":")
prefix (str (first multibase-value))
base-key (subs multibase-value 1)
_ (when (not= prefix base58btc)
(throw (ex-info (str "The prefix " (pr-str prefix) " does not map to a supported multibase encoding.")
{:value multibase-value
:prefix prefix})))
multicodec (alphabase/bytes->hex (base58/decode base-key))
pubkey-header (subs multicodec 0 2)
pubkey (subs multicodec 2)]
(when (not= pubkey-header secp256k1-pub)
(throw (ex-info (str "The multicodec header " (pr-str pubkey-header) " does not map to a supported multicodec encoding.")
{:value multicodec
:header pubkey-header})))
pubkey))
211 changes: 59 additions & 152 deletions src/fluree/db/json_ld/credential.cljc

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion src/fluree/db/util/core.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -387,4 +387,4 @@
([vol f arg1 arg2]
(clojure.core/vswap! vol f arg1 arg2))
([vol f arg1 arg2 arg3]
(clojure.core/vswap! vol f arg1 arg2 arg3)))
(clojure.core/vswap! vol f arg1 arg2 arg3)))
90 changes: 90 additions & 0 deletions test/fluree/db/json_ld/credential_test.cljc
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
(ns fluree.db.json-ld.credential-test
(:require [fluree.db.json-ld.credential :as cred]
[clojure.core.async :as async]
#?(:clj [clojure.test :as t :refer [deftest testing is]]
:cljs [cljs.test :as t :refer [deftest testing is] :include-macros true])))

(def auth
{:id "did:fluree:TfHgFTQQiJMHaK1r1qxVPZ3Ridj9pCozqnh"
:public "03b160698617e3b4cd621afd96c0591e33824cb9753ab2f1dace567884b4e242b0"
:private "509553eece84d5a410f1012e8e19e84e938f226aa3ad144e2d12f36df0f51c1e"})

(def example-cred-subject {"@context" {"a" "http://a.com/"} "a:foo" "bar"})

(def clj-generated-jws
"eyJhbGciOiJFUzI1NkstUiIsImI2NCI6ZmFsc2UsImNyaXQiOlsiYjY0Il19..HDBFAiEA80-G5gUH6BT9D1Mc-YyWbjuwbL7nKfWj6BrsHS6whQ0CIAcjzJvo0sW52FIlgvxy0hPBKNWolIwLvoedG_4HQu_V")

(def cljs-generated-jws
"eyJhbGciOiJFUzI1NkstUiIsImI2NCI6ZmFsc2UsImNyaXQiOlsiYjY0Il19..HDBFAiEAy9MuRjVn_vwvEgQlsCJNnSYwCJEWU_UOg5U_R8--87wCID-qficJv-aCUotctcFGX-xTky1E08W2Y7utUCJZ3AZY")

(def expected-credential
{"@context" "https://www.w3.org/2018/credentials/v1"
"id" ""
"type" ["VerifiableCredential" "CommitProof"]
"issuer" "did:fluree:TfHgFTQQiJMHaK1r1qxVPZ3Ridj9pCozqnh"
"issuanceDate" "1970-01-01T00:00:00.00000Z"
"credentialSubject" {"@context" {"a" "http://a.com/"} "a:foo" "bar"}
"proof" {"type" "EcdsaSecp256k1RecoverySignature2020"
"created" "1970-01-01T00:00:00.00000Z"
"verificationMethod" "did:key:z6DuABnw7XPbMksZo5wY4HweN8wPkEd7rCQM4YGgu8hPqrd5"
"proofPurpose" "assertionMethod"
"jws" #?(:clj clj-generated-jws
:cljs cljs-generated-jws)}})

#?(:clj
(deftest credential-test
(with-redefs [fluree.db.util.core/current-time-iso (constantly "1970-01-01T00:00:00.00000Z")]
(testing "generate"
(let [cred (async/<!! (cred/generate example-cred-subject (:private auth)))]
(is (= expected-credential
cred))))
(testing "verify correct signature"
(let [clj-result (async/<!! (cred/verify expected-credential))
cljs-result (async/<!! (cred/verify (assoc-in expected-credential ["proof" "jws"] cljs-generated-jws)))]
(is (= true clj-result))
(is (= true cljs-result))))
(testing "verify incorrect signature"
(let [wrong-cred (assoc expected-credential "credentialSubject" {"@context" {"a" "http://a.com/"} "a:foo" "DIFFERENT!"})]
(is (= "Unverifiable credential"
(-> (async/<!! (cred/verify wrong-cred))
(Throwable->map)
(:cause)))))))))

#?(:cljs
(deftest generate
(t/async done
(async/go
(with-redefs [fluree.db.util.core/current-time-iso (constantly "1970-01-01T00:00:00.00000Z")]
(let [cred (async/<! (cred/generate example-cred-subject (:private auth)))]
(is (= expected-credential
cred))
(done)))))))

#?(:cljs
(deftest verify-correct-signature
(t/async done
(async/go
(with-redefs [fluree.db.util.core/current-time-iso (constantly "1970-01-01T00:00:00.00000Z")]
(let [cljs-result (async/<! (cred/verify expected-credential))
clj-result (async/<! (cred/verify (assoc-in expected-credential ["proof" "jws"] clj-generated-jws)))]
(is (= true cljs-result))
(is (= true clj-result))
(done)))))))

#?(:cljs
(deftest verify-incorrect-signature
(t/async done
(async/go
(with-redefs [fluree.db.util.core/current-time-iso (constantly "1970-01-01T00:00:00.00000Z")]
(let [wrong-cred (assoc expected-credential "credentialSubject" {"@context" {"a" "http://a.com/"} "a:foo" "DIFFERENT!"})]
(is (= "Unverifiable credential"
(-> (async/<! (cred/verify wrong-cred))
(.-message e))))
(done)))))))

(comment
#?(:cljs

(cljs.test/run-tests)
)
,)