mirror of
https://github.com/sonr-io/sonr.git
synced 2026-08-03 01:41:44 +00:00
feature/refactor did state (#10)
* feat(did): remove account types * feat: Refactor Property to Proof in zkprop.go * feat: add ZKP proof mechanism for verifications * fix: return bool and error from pinInitialVault * feat: implement KeyshareSet for managing user and validator keyshares * feat: Update Credential type in protobuf * feat: update credential schema with sign count * feat: migrate and modules to middleware * refactor: rename vault module to ORM * chore(dwn): add service worker registration to index template * feat: integrate service worker for offline functionality * refactor(did): use DIDNamespace enum for verification method in proto reflection * refactor: update protobuf definitions to support Keyshare * feat: expose did keeper in app keepers * Add Motr Web App * refactor: rename motr/handlers/discovery.go to motr/handlers/openid.go * refactor: move session related code to middleware * feat: add database operations for managing assets, chains, and credentials * feat: add htmx support for UI updates * refactor: extract common helper scripts * chore: remove unused storage GUI components * refactor: Move frontend rendering to dedicated handlers * refactor: rename to * refactor: move alert implementation to templ * feat: add alert component with icon, title, and message * feat: add new RequestHeaders struct to store request headers * Feature/create home view (#9) * refactor: move view logic to new htmx handler * refactor: remove unnecessary dependencies * refactor: remove unused dependencies * feat(devbox): integrate air for local development * feat: implement openid connect discovery document * refactor: rename to * refactor(did): update service handling to support DNS discovery * feat: add support for user and validator keyshares * refactor: move keyshare signing logic to signer
This commit is contained in:
+148
-73
@@ -4,12 +4,103 @@ import (
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
|
||||
"github.com/go-webauthn/webauthn/protocol"
|
||||
|
||||
"github.com/go-webauthn/webauthn/protocol/webauthncose"
|
||||
didv1 "github.com/onsonr/sonr/api/did/v1"
|
||||
"github.com/onsonr/sonr/x/did/types"
|
||||
)
|
||||
|
||||
func FormatEC2PublicKey(key *webauthncose.EC2PublicKeyData) (*types.JWK, error) {
|
||||
func APIFormatDIDNamespace(namespace types.DIDNamespace) didv1.DIDNamespace {
|
||||
return didv1.DIDNamespace(namespace)
|
||||
}
|
||||
|
||||
func APIFormatDIDNamespaces(namespaces []types.DIDNamespace) []didv1.DIDNamespace {
|
||||
var s []didv1.DIDNamespace
|
||||
for _, namespace := range namespaces {
|
||||
s = append(s, APIFormatDIDNamespace(namespace))
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func APIFormatKeyRole(role types.KeyRole) didv1.KeyRole {
|
||||
return didv1.KeyRole(role)
|
||||
}
|
||||
|
||||
func APIFormatKeyAlgorithm(algorithm types.KeyAlgorithm) didv1.KeyAlgorithm {
|
||||
return didv1.KeyAlgorithm(algorithm)
|
||||
}
|
||||
|
||||
func APIFormatKeyEncoding(encoding types.KeyEncoding) didv1.KeyEncoding {
|
||||
return didv1.KeyEncoding(encoding)
|
||||
}
|
||||
|
||||
func APIFormatKeyCurve(curve types.KeyCurve) didv1.KeyCurve {
|
||||
return didv1.KeyCurve(curve)
|
||||
}
|
||||
|
||||
func APIFormatKeyType(keyType types.KeyType) didv1.KeyType {
|
||||
return didv1.KeyType(keyType)
|
||||
}
|
||||
|
||||
func APIFormatPermissions(permissions *types.Permissions) *didv1.Permissions {
|
||||
if permissions == nil {
|
||||
return nil
|
||||
}
|
||||
p := didv1.Permissions{
|
||||
Grants: APIFormatDIDNamespaces(permissions.Grants),
|
||||
Scopes: APIFormatPermissionScopes(permissions.Scopes),
|
||||
}
|
||||
return &p
|
||||
}
|
||||
|
||||
func APIFormatPermissionScope(scope types.PermissionScope) didv1.PermissionScope {
|
||||
return didv1.PermissionScope(scope)
|
||||
}
|
||||
|
||||
func APIFormatPermissionScopes(scopes []types.PermissionScope) []didv1.PermissionScope {
|
||||
var s []didv1.PermissionScope
|
||||
for _, scope := range scopes {
|
||||
s = append(s, APIFormatPermissionScope(scope))
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func APIFormatServiceRecord(service *types.Service) *didv1.ServiceRecord {
|
||||
return &didv1.ServiceRecord{
|
||||
Id: service.Id,
|
||||
ServiceType: service.ServiceType,
|
||||
Authority: service.Authority,
|
||||
Origin: service.Origin,
|
||||
Description: service.Description,
|
||||
ServiceEndpoints: service.ServiceEndpoints,
|
||||
Permissions: APIFormatPermissions(service.Permissions),
|
||||
}
|
||||
}
|
||||
|
||||
func APIFormatPubKeyJWK(jwk *types.PubKey_JWK) *didv1.PubKey_JWK {
|
||||
return &didv1.PubKey_JWK{
|
||||
Kty: jwk.Kty,
|
||||
Crv: jwk.Crv,
|
||||
X: jwk.X,
|
||||
Y: jwk.Y,
|
||||
N: jwk.N,
|
||||
E: jwk.E,
|
||||
}
|
||||
}
|
||||
|
||||
func APIFormatPubKey(key *types.PubKey) *didv1.PubKey {
|
||||
return &didv1.PubKey{
|
||||
Role: APIFormatKeyRole(key.GetRole()),
|
||||
Algorithm: APIFormatKeyAlgorithm(key.GetAlgorithm()),
|
||||
Encoding: APIFormatKeyEncoding(key.GetEncoding()),
|
||||
Curve: APIFormatKeyCurve(key.GetCurve()),
|
||||
KeyType: APIFormatKeyType(key.GetKeyType()),
|
||||
Raw: key.GetRaw(),
|
||||
}
|
||||
}
|
||||
|
||||
func FormatEC2PublicKey(key *webauthncose.EC2PublicKeyData) (*types.PubKey_JWK, error) {
|
||||
curve, err := GetCOSECurveName(key.Curve)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -25,7 +116,7 @@ func FormatEC2PublicKey(key *webauthncose.EC2PublicKeyData) (*types.JWK, error)
|
||||
return MapToJWK(jwkMap)
|
||||
}
|
||||
|
||||
func FormatRSAPublicKey(key *webauthncose.RSAPublicKeyData) (*types.JWK, error) {
|
||||
func FormatRSAPublicKey(key *webauthncose.RSAPublicKeyData) (*types.PubKey_JWK, error) {
|
||||
jwkMap := map[string]interface{}{
|
||||
"kty": "RSA",
|
||||
"n": base64.RawURLEncoding.EncodeToString(key.Modulus),
|
||||
@@ -35,8 +126,8 @@ func FormatRSAPublicKey(key *webauthncose.RSAPublicKeyData) (*types.JWK, error)
|
||||
return MapToJWK(jwkMap)
|
||||
}
|
||||
|
||||
func FormatOKPPublicKey(key *webauthncose.OKPPublicKeyData) (*types.JWK, error) {
|
||||
curve, err := getOKPCurveName(key.Curve)
|
||||
func FormatOKPPublicKey(key *webauthncose.OKPPublicKeyData) (*types.PubKey_JWK, error) {
|
||||
curve, err := GetOKPCurveName(key.Curve)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -50,8 +141,8 @@ func FormatOKPPublicKey(key *webauthncose.OKPPublicKeyData) (*types.JWK, error)
|
||||
return MapToJWK(jwkMap)
|
||||
}
|
||||
|
||||
func MapToJWK(m map[string]interface{}) (*types.JWK, error) {
|
||||
jwk := &types.JWK{}
|
||||
func MapToJWK(m map[string]interface{}) (*types.PubKey_JWK, error) {
|
||||
jwk := &types.PubKey_JWK{}
|
||||
for k, v := range m {
|
||||
switch k {
|
||||
case "kty":
|
||||
@@ -84,7 +175,7 @@ func GetCOSECurveName(curveID int64) (string, error) {
|
||||
}
|
||||
}
|
||||
|
||||
func getOKPCurveName(curveID int64) (string, error) {
|
||||
func GetOKPCurveName(curveID int64) (string, error) {
|
||||
switch curveID {
|
||||
case int64(webauthncose.Ed25519):
|
||||
return "Ed25519", nil
|
||||
@@ -93,84 +184,68 @@ func getOKPCurveName(curveID int64) (string, error) {
|
||||
}
|
||||
}
|
||||
|
||||
func ModulePubKeyToAPI(pk *types.PubKey) *didv1.PubKey {
|
||||
return &didv1.PubKey{
|
||||
Role: ModuleKeyRoleToAPI(pk.GetRole()),
|
||||
Algorithm: ModuleKeyAlgorithmToAPI(pk.GetAlgorithm()),
|
||||
Encoding: ModuleKeyEncodingToAPI(pk.GetEncoding()),
|
||||
Curve: ModuleKeyCurveToAPI(pk.GetCurve()),
|
||||
KeyType: ModuleKeyTypeToAPI(pk.GetKeyType()),
|
||||
Raw: pk.GetRaw(),
|
||||
// NormalizeTransports returns the transports as strings
|
||||
func NormalizeTransports(transports []protocol.AuthenticatorTransport) []string {
|
||||
tss := make([]string, len(transports))
|
||||
for i, t := range transports {
|
||||
tss[i] = string(t)
|
||||
}
|
||||
return tss
|
||||
}
|
||||
|
||||
// GetTransports returns the protocol.AuthenticatorTransport
|
||||
func ModuleTransportsToProtocol(transport []string) []protocol.AuthenticatorTransport {
|
||||
tss := make([]protocol.AuthenticatorTransport, len(transport))
|
||||
for i, t := range transport {
|
||||
tss[i] = protocol.AuthenticatorTransport(t)
|
||||
}
|
||||
return tss
|
||||
}
|
||||
|
||||
// ModuleFormatAPIServiceRecord formats a service record for the module
|
||||
func ModuleFormatAPIServiceRecord(service *didv1.ServiceRecord) *types.Service {
|
||||
return &types.Service{
|
||||
Id: service.Id,
|
||||
ServiceType: service.ServiceType,
|
||||
Authority: service.Authority,
|
||||
Origin: service.Origin,
|
||||
Description: service.Description,
|
||||
ServiceEndpoints: service.ServiceEndpoints,
|
||||
Permissions: ModuleFormatAPIPermissions(service.Permissions),
|
||||
}
|
||||
}
|
||||
|
||||
func ModuleKeyRoleToAPI(role types.KeyRole) didv1.KeyRole {
|
||||
switch role {
|
||||
case types.KeyRole_KEY_ROLE_INVOCATION:
|
||||
return didv1.KeyRole_KEY_ROLE_INVOCATION
|
||||
case types.KeyRole_KEY_ROLE_ASSERTION:
|
||||
return didv1.KeyRole_KEY_ROLE_ASSERTION
|
||||
case types.KeyRole_KEY_ROLE_DELEGATION:
|
||||
return didv1.KeyRole_KEY_ROLE_DELEGATION
|
||||
default:
|
||||
return didv1.KeyRole_KEY_ROLE_INVOCATION
|
||||
func ModuleFormatAPIPermissions(permissions *didv1.Permissions) *types.Permissions {
|
||||
if permissions == nil {
|
||||
return nil
|
||||
}
|
||||
p := types.Permissions{
|
||||
Grants: ModuleFormatAPIDIDNamespaces(permissions.Grants),
|
||||
Scopes: ModuleFormatAPIPermissionScopes(permissions.Scopes),
|
||||
}
|
||||
return &p
|
||||
}
|
||||
|
||||
func ModuleKeyAlgorithmToAPI(algorithm types.KeyAlgorithm) didv1.KeyAlgorithm {
|
||||
switch algorithm {
|
||||
case types.KeyAlgorithm_KEY_ALGORITHM_ES256K:
|
||||
return didv1.KeyAlgorithm_KEY_ALGORITHM_ES256K
|
||||
case types.KeyAlgorithm_KEY_ALGORITHM_ES256:
|
||||
return didv1.KeyAlgorithm_KEY_ALGORITHM_ES256
|
||||
case types.KeyAlgorithm_KEY_ALGORITHM_ES384:
|
||||
return didv1.KeyAlgorithm_KEY_ALGORITHM_ES384
|
||||
case types.KeyAlgorithm_KEY_ALGORITHM_ES512:
|
||||
return didv1.KeyAlgorithm_KEY_ALGORITHM_ES512
|
||||
case types.KeyAlgorithm_KEY_ALGORITHM_EDDSA:
|
||||
return didv1.KeyAlgorithm_KEY_ALGORITHM_EDDSA
|
||||
default:
|
||||
return didv1.KeyAlgorithm_KEY_ALGORITHM_ES256K
|
||||
}
|
||||
func ModuleFormatAPIPermissionScope(scope didv1.PermissionScope) types.PermissionScope {
|
||||
return types.PermissionScope(scope)
|
||||
}
|
||||
|
||||
func ModuleKeyCurveToAPI(curve types.KeyCurve) didv1.KeyCurve {
|
||||
switch curve {
|
||||
case types.KeyCurve_KEY_CURVE_P256:
|
||||
return didv1.KeyCurve_KEY_CURVE_P256
|
||||
case types.KeyCurve_KEY_CURVE_SECP256K1:
|
||||
return didv1.KeyCurve_KEY_CURVE_SECP256K1
|
||||
case types.KeyCurve_KEY_CURVE_BLS12381:
|
||||
return didv1.KeyCurve_KEY_CURVE_BLS12381
|
||||
case types.KeyCurve_KEY_CURVE_KECCAK256:
|
||||
return didv1.KeyCurve_KEY_CURVE_KECCAK256
|
||||
default:
|
||||
return didv1.KeyCurve_KEY_CURVE_P256
|
||||
func ModuleFormatAPIPermissionScopes(scopes []didv1.PermissionScope) []types.PermissionScope {
|
||||
var s []types.PermissionScope
|
||||
for _, scope := range scopes {
|
||||
s = append(s, ModuleFormatAPIPermissionScope(scope))
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func ModuleKeyEncodingToAPI(encoding types.KeyEncoding) didv1.KeyEncoding {
|
||||
switch encoding {
|
||||
case types.KeyEncoding_KEY_ENCODING_RAW:
|
||||
return didv1.KeyEncoding_KEY_ENCODING_RAW
|
||||
case types.KeyEncoding_KEY_ENCODING_HEX:
|
||||
return didv1.KeyEncoding_KEY_ENCODING_HEX
|
||||
case types.KeyEncoding_KEY_ENCODING_MULTIBASE:
|
||||
return didv1.KeyEncoding_KEY_ENCODING_MULTIBASE
|
||||
default:
|
||||
return didv1.KeyEncoding_KEY_ENCODING_RAW
|
||||
}
|
||||
func ModuleFormatAPIDIDNamespace(namespace didv1.DIDNamespace) types.DIDNamespace {
|
||||
return types.DIDNamespace(namespace)
|
||||
}
|
||||
|
||||
func ModuleKeyTypeToAPI(keyType types.KeyType) didv1.KeyType {
|
||||
switch keyType {
|
||||
case types.KeyType_KEY_TYPE_BIP32:
|
||||
return didv1.KeyType_KEY_TYPE_BIP32
|
||||
case types.KeyType_KEY_TYPE_ZK:
|
||||
return didv1.KeyType_KEY_TYPE_ZK
|
||||
case types.KeyType_KEY_TYPE_WEBAUTHN:
|
||||
return didv1.KeyType_KEY_TYPE_WEBAUTHN
|
||||
default:
|
||||
return didv1.KeyType_KEY_TYPE_BIP32
|
||||
func ModuleFormatAPIDIDNamespaces(namespaces []didv1.DIDNamespace) []types.DIDNamespace {
|
||||
var s []types.DIDNamespace
|
||||
for _, namespace := range namespaces {
|
||||
s = append(s, ModuleFormatAPIDIDNamespace(namespace))
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
package builder
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/labstack/echo/v4"
|
||||
"gopkg.in/macaroon.v2"
|
||||
|
||||
"gopkg.in/macaroon-bakery.v2/bakery/checkers"
|
||||
)
|
||||
|
||||
var PermissionNamespace *checkers.Namespace
|
||||
|
||||
func ValidateMacaroonMiddleware(secretKey []byte, location string) echo.MiddlewareFunc {
|
||||
return func(next echo.HandlerFunc) echo.HandlerFunc {
|
||||
return func(c echo.Context) error {
|
||||
// Extract the macaroon from the Authorization header
|
||||
auth := c.Request().Header.Get("Authorization")
|
||||
if auth == "" {
|
||||
return c.JSON(http.StatusUnauthorized, map[string]string{"error": "Missing Authorization header"})
|
||||
}
|
||||
|
||||
// Decode the macaroon
|
||||
mac, err := macaroon.Base64Decode([]byte(auth))
|
||||
if err != nil {
|
||||
return c.JSON(http.StatusBadRequest, map[string]string{"error": "Invalid macaroon encoding"})
|
||||
}
|
||||
|
||||
token, err := macaroon.New(secretKey, mac, location, macaroon.LatestVersion)
|
||||
if err != nil {
|
||||
return c.JSON(http.StatusBadRequest, map[string]string{"error": "Invalid macaroon"})
|
||||
}
|
||||
|
||||
// Verify the macaroon
|
||||
err = token.Verify(secretKey, func(caveat string) error {
|
||||
// Implement your caveat verification logic here
|
||||
// For example, you might check if the caveat is still valid (e.g., not expired)
|
||||
return nil // Return nil if the caveat is valid
|
||||
}, nil)
|
||||
if err != nil {
|
||||
return c.JSON(http.StatusUnauthorized, map[string]string{"error": "Invalid macaroon"})
|
||||
}
|
||||
|
||||
// Macaroon is valid, proceed to the next handler
|
||||
return next(c)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -52,7 +52,7 @@ type PublicKeyCredentialCreationOptions struct {
|
||||
Extensions AuthenticationExtensions `json:"extensions,omitempty"`
|
||||
}
|
||||
|
||||
func NewRegistrationOptions(origin string, subject string, vaultCID string, params *types.Params) (*PublicKeyCredentialCreationOptions, error) {
|
||||
func GetPublicKeyCredentialCreationOptions(origin string, subject string, vaultCID string, params *types.Params) (*PublicKeyCredentialCreationOptions, error) {
|
||||
chal, err := CreateChallenge()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"fmt"
|
||||
|
||||
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
|
||||
didv1 "github.com/onsonr/sonr/api/did/v1"
|
||||
"github.com/onsonr/sonr/x/did/types"
|
||||
|
||||
"github.com/go-webauthn/webauthn/protocol/webauthncose"
|
||||
@@ -33,17 +34,17 @@ func CreateAuthnVerification(namespace types.DIDNamespace, issuer string, contro
|
||||
}
|
||||
|
||||
// CreateWalletVerification creates a new verification method for a wallet
|
||||
func CreateWalletVerification(namespace types.DIDNamespace, controller string, pubkey *types.PubKey, identifier string) *types.VerificationMethod {
|
||||
return &types.VerificationMethod{
|
||||
Method: namespace,
|
||||
func CreateWalletVerification(namespace types.DIDNamespace, controller string, pubkey *types.PubKey, identifier string) *didv1.VerificationMethod {
|
||||
return &didv1.VerificationMethod{
|
||||
Method: APIFormatDIDNamespace(namespace),
|
||||
Controller: controller,
|
||||
PublicKey: pubkey,
|
||||
PublicKey: APIFormatPubKey(pubkey),
|
||||
Id: identifier,
|
||||
}
|
||||
}
|
||||
|
||||
// ExtractWebAuthnPublicKey parses the raw public key bytes and returns a JWK representation
|
||||
func ExtractWebAuthnPublicKey(keyBytes []byte) (*types.JWK, error) {
|
||||
func ExtractWebAuthnPublicKey(keyBytes []byte) (*types.PubKey_JWK, error) {
|
||||
key, err := webauthncose.ParsePublicKey(keyBytes)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to parse public key: %w", err)
|
||||
@@ -62,8 +63,8 @@ func ExtractWebAuthnPublicKey(keyBytes []byte) (*types.JWK, error) {
|
||||
}
|
||||
|
||||
// NewInitialWalletAccounts creates a new set of verification methods for a wallet
|
||||
func NewInitialWalletAccounts(controller string, pubkey *types.PubKey) ([]*types.VerificationMethod, error) {
|
||||
var verificationMethods []*types.VerificationMethod
|
||||
func NewInitialWalletAccounts(controller string, pubkey *types.PubKey) ([]*didv1.VerificationMethod, error) {
|
||||
var verificationMethods []*didv1.VerificationMethod
|
||||
for method, chain := range types.InitialChainCodes {
|
||||
nk, err := computeBip32AccountPublicKey(pubkey, chain, 0)
|
||||
if err != nil {
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
package builder
|
||||
|
||||
import (
|
||||
"github.com/onsonr/sonr/x/did/types"
|
||||
"gopkg.in/macaroon-bakery.v2/bakery/checkers"
|
||||
)
|
||||
|
||||
var (
|
||||
GenericPermissionScopeStrings = [...]string{
|
||||
"profile.name",
|
||||
"identifiers.email",
|
||||
"identifiers.phone",
|
||||
"transactions.read",
|
||||
"transactions.write",
|
||||
"wallets.read",
|
||||
"wallets.create",
|
||||
"wallets.subscribe",
|
||||
"wallets.update",
|
||||
"transactions.verify",
|
||||
"transactions.broadcast",
|
||||
"admin.user",
|
||||
"admin.validator",
|
||||
}
|
||||
|
||||
StringToModulePermissionScope = map[string]types.PermissionScope{
|
||||
"PERMISSION_SCOPE_UNSPECIFIED": types.PermissionScope_PERMISSION_SCOPE_UNSPECIFIED,
|
||||
"PERMISSION_SCOPE_BASIC_INFO": types.PermissionScope_PERMISSION_SCOPE_BASIC_INFO,
|
||||
"PERMISSION_SCOPE_IDENTIFIERS_EMAIL": types.PermissionScope_PERMISSION_SCOPE_PERMISSIONS_READ,
|
||||
"PERMISSION_SCOPE_IDENTIFIERS_PHONE": types.PermissionScope_PERMISSION_SCOPE_PERMISSIONS_WRITE,
|
||||
"PERMISSION_SCOPE_TRANSACTIONS_READ": types.PermissionScope_PERMISSION_SCOPE_TRANSACTIONS_READ,
|
||||
"PERMISSION_SCOPE_TRANSACTIONS_WRITE": types.PermissionScope_PERMISSION_SCOPE_TRANSACTIONS_WRITE,
|
||||
"PERMISSION_SCOPE_WALLETS_READ": types.PermissionScope_PERMISSION_SCOPE_WALLETS_READ,
|
||||
"PERMISSION_SCOPE_WALLETS_CREATE": types.PermissionScope_PERMISSION_SCOPE_WALLETS_CREATE,
|
||||
"PERMISSION_SCOPE_WALLETS_SUBSCRIBE": types.PermissionScope_PERMISSION_SCOPE_WALLETS_SUBSCRIBE,
|
||||
"PERMISSION_SCOPE_WALLETS_UPDATE": types.PermissionScope_PERMISSION_SCOPE_WALLETS_UPDATE,
|
||||
"PERMISSION_SCOPE_TRANSACTIONS_VERIFY": types.PermissionScope_PERMISSION_SCOPE_TRANSACTIONS_VERIFY,
|
||||
"PERMISSION_SCOPE_TRANSACTIONS_BROADCAST": types.PermissionScope_PERMISSION_SCOPE_TRANSACTIONS_BROADCAST,
|
||||
"PERMISSION_SCOPE_ADMIN_USER": types.PermissionScope_PERMISSION_SCOPE_ADMIN_USER,
|
||||
"PERMISSION_SCOPE_ADMIN_VALIDATOR": types.PermissionScope_PERMISSION_SCOPE_ADMIN_VALIDATOR,
|
||||
}
|
||||
)
|
||||
|
||||
func ResolvePermissionScope(scope string) (types.PermissionScope, bool) {
|
||||
uriToPrefix := make(map[string]string)
|
||||
for _, scope := range GenericPermissionScopeStrings {
|
||||
uriToPrefix["https://example.com/auth/"+scope] = scope
|
||||
}
|
||||
PermissionNamespace := checkers.NewNamespace(uriToPrefix)
|
||||
|
||||
prefix, ok := PermissionNamespace.Resolve("https://example.com/auth/" + scope)
|
||||
if !ok {
|
||||
return 0, false
|
||||
}
|
||||
permScope, ok := StringToModulePermissionScope[prefix]
|
||||
return permScope, ok
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
package builder
|
||||
|
||||
import (
|
||||
"github.com/onsonr/crypto"
|
||||
"github.com/onsonr/sonr/x/did/types"
|
||||
)
|
||||
|
||||
type Signer interface {
|
||||
Sign(msg []byte) ([]byte, error)
|
||||
Verify(msg []byte, sig []byte) error
|
||||
PublicKey() []byte
|
||||
}
|
||||
|
||||
type signer struct {
|
||||
user *types.Keyshare
|
||||
val *types.Keyshare
|
||||
}
|
||||
|
||||
func (k signer) Sign(msg []byte) ([]byte, error) {
|
||||
valSignFunc, err := crypto.GetSignFunc(k.val, msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
usrSignFunc, err := crypto.GetSignFunc(k.user, msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
sig, err := crypto.RunMPCSign(valSignFunc, usrSignFunc)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return crypto.SerializeMPCSignature(sig)
|
||||
}
|
||||
|
||||
func (k signer) Verify(msg []byte, sig []byte) error {
|
||||
sigMpc, err := crypto.DeserializeMPCSignature(sig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
pk, err := crypto.GetECDSAPublicKey(k.val)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ok := crypto.VerifyMPCSignature(sigMpc, msg, pk)
|
||||
if !ok {
|
||||
return types.ErrInvalidSignature
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (k signer) PublicKey() []byte {
|
||||
if k.user != nil {
|
||||
return k.user.PublicKey
|
||||
}
|
||||
if k.val != nil {
|
||||
return k.val.PublicKey
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -4,8 +4,63 @@ import (
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"reflect"
|
||||
|
||||
"github.com/go-webauthn/webauthn/protocol"
|
||||
)
|
||||
|
||||
// Credential contains all needed information about a WebAuthn credential for storage.
|
||||
type Credential struct {
|
||||
Subject string `json:"handle"`
|
||||
AttestationType string `json:"attestationType"`
|
||||
Origin string `json:"origin"`
|
||||
CredentialID []byte `json:"id"`
|
||||
PublicKey []byte `json:"publicKey"`
|
||||
Transport []string `json:"transport"`
|
||||
SignCount uint32 `json:"signCount"`
|
||||
UserPresent bool `json:"userPresent"`
|
||||
UserVerified bool `json:"userVerified"`
|
||||
BackupEligible bool `json:"backupEligible"`
|
||||
BackupState bool `json:"backupState"`
|
||||
CloneWarning bool `json:"cloneWarning"`
|
||||
}
|
||||
|
||||
// NewCredential will return a credential pointer on successful validation of a registration response.
|
||||
func NewCredential(c *protocol.ParsedCredentialCreationData, origin, handle string) *Credential {
|
||||
return &Credential{
|
||||
Subject: handle,
|
||||
Origin: origin,
|
||||
AttestationType: c.Response.AttestationObject.Format,
|
||||
CredentialID: c.Response.AttestationObject.AuthData.AttData.CredentialID,
|
||||
PublicKey: c.Response.AttestationObject.AuthData.AttData.CredentialPublicKey,
|
||||
Transport: NormalizeTransports(c.Response.Transports),
|
||||
SignCount: c.Response.AttestationObject.AuthData.Counter,
|
||||
UserPresent: c.Response.AttestationObject.AuthData.Flags.HasUserPresent(),
|
||||
UserVerified: c.Response.AttestationObject.AuthData.Flags.HasUserVerified(),
|
||||
BackupEligible: c.Response.AttestationObject.AuthData.Flags.HasBackupEligible(),
|
||||
BackupState: c.Response.AttestationObject.AuthData.Flags.HasAttestedCredentialData(),
|
||||
}
|
||||
}
|
||||
|
||||
// Descriptor converts a Credential into a protocol.CredentialDescriptor.
|
||||
func (c *Credential) Descriptor() protocol.CredentialDescriptor {
|
||||
return protocol.CredentialDescriptor{
|
||||
Type: protocol.PublicKeyCredentialType,
|
||||
CredentialID: c.CredentialID,
|
||||
Transport: ModuleTransportsToProtocol(c.Transport),
|
||||
AttestationType: c.AttestationType,
|
||||
}
|
||||
}
|
||||
|
||||
// This is a signal that the authenticator may be cloned, see CloneWarning above for more information.
|
||||
func (a *Credential) UpdateCounter(authDataCount uint32) {
|
||||
if authDataCount <= a.SignCount && (authDataCount != 0 || a.SignCount != 0) {
|
||||
a.CloneWarning = true
|
||||
return
|
||||
}
|
||||
|
||||
a.SignCount = authDataCount
|
||||
}
|
||||
|
||||
type CredentialDescriptor struct {
|
||||
// The valid credential types.
|
||||
Type CredentialType `json:"type"`
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
package context
|
||||
@@ -1,4 +1,4 @@
|
||||
package middleware
|
||||
package context
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -0,0 +1,60 @@
|
||||
package keeper
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/onsonr/sonr/x/did/builder"
|
||||
"github.com/onsonr/sonr/x/did/types"
|
||||
"google.golang.org/grpc/peer"
|
||||
)
|
||||
|
||||
type Context struct {
|
||||
SDKCtx sdk.Context
|
||||
Keeper Keeper
|
||||
Peer *peer.Peer
|
||||
}
|
||||
|
||||
func (k Keeper) CurrentCtx(goCtx context.Context) Context {
|
||||
ctx := sdk.UnwrapSDKContext(goCtx)
|
||||
peer, _ := peer.FromContext(goCtx)
|
||||
return Context{SDKCtx: ctx, Peer: peer, Keeper: k}
|
||||
}
|
||||
|
||||
func (c Context) Params() *types.Params {
|
||||
return c.Keeper.GetParams(c.SDK())
|
||||
}
|
||||
|
||||
func (c Context) SDK() sdk.Context {
|
||||
return c.SDKCtx
|
||||
}
|
||||
|
||||
func (c Context) IsAnonymous() bool {
|
||||
if c.Peer == nil {
|
||||
return true
|
||||
}
|
||||
return c.Peer.Addr == nil
|
||||
}
|
||||
|
||||
func (c Context) PeerID() string {
|
||||
if c.Peer == nil {
|
||||
return ""
|
||||
}
|
||||
return c.Peer.Addr.String()
|
||||
}
|
||||
|
||||
func (c Context) GetService(origin string) (*types.Service, error) {
|
||||
rec, err := c.Keeper.OrmDB.ServiceRecordTable().GetByOrigin(c.SDK(), origin)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return builder.ModuleFormatAPIServiceRecord(rec), nil
|
||||
}
|
||||
|
||||
func (c Context) GetServiceInfo(origin string) *types.ServiceInfo {
|
||||
rec, _ := c.GetService(origin)
|
||||
if rec == nil {
|
||||
return &types.ServiceInfo{Exists: false, Origin: origin, Fingerprint: types.ComputeOriginTXTRecord(origin)}
|
||||
}
|
||||
return &types.ServiceInfo{Exists: true, Origin: origin, Fingerprint: types.ComputeOriginTXTRecord(origin), Service: rec}
|
||||
}
|
||||
@@ -66,7 +66,8 @@ func (k Keeper) GetParams(ctx sdk.Context) *types.Params {
|
||||
if err != nil {
|
||||
p = types.DefaultParams()
|
||||
}
|
||||
return &p
|
||||
params := p.ActiveParams(k.HasIPFSConnection())
|
||||
return ¶ms
|
||||
}
|
||||
|
||||
// GetExpirationBlockHeight returns the block height at which the given duration will have passed
|
||||
|
||||
@@ -23,11 +23,11 @@ func (k Keeper) assembleInitialVault(ctx sdk.Context) (string, int64, error) {
|
||||
}
|
||||
|
||||
// pinInitialVault pins the initial vault to the local IPFS node
|
||||
func (k Keeper) pinInitialVault(_ sdk.Context, cid string, address string) error {
|
||||
func (k Keeper) pinInitialVault(_ sdk.Context, cid string, address string) (bool, error) {
|
||||
// Resolve the path
|
||||
path, err := path.NewPath(cid)
|
||||
if err != nil {
|
||||
return err
|
||||
return false, err
|
||||
}
|
||||
|
||||
// 1. Initialize vault.db sqlite database in local IPFS with Mount
|
||||
@@ -37,13 +37,13 @@ func (k Keeper) pinInitialVault(_ sdk.Context, cid string, address string) error
|
||||
// 3. Publish the path to the IPNS
|
||||
_, err = k.ipfsClient.Name().Publish(context.Background(), path, options.Name.Key(address))
|
||||
if err != nil {
|
||||
return err
|
||||
return false, err
|
||||
}
|
||||
|
||||
// 4. Insert the accounts into x/auth
|
||||
|
||||
// 5. Insert the controller into state
|
||||
return nil
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// GetFromIPFS gets a file from the local IPFS node
|
||||
|
||||
@@ -14,7 +14,7 @@ import (
|
||||
"github.com/ipfs/kubo/client/rpc"
|
||||
|
||||
apiv1 "github.com/onsonr/sonr/api/did/v1"
|
||||
middleware "github.com/onsonr/sonr/x/did/middleware"
|
||||
middleware "github.com/onsonr/sonr/x/did/context"
|
||||
"github.com/onsonr/sonr/x/did/types"
|
||||
)
|
||||
|
||||
@@ -90,7 +90,7 @@ func NewKeeper(
|
||||
|
||||
// IsClaimedServiceOrigin checks if a service origin is unclaimed
|
||||
func (k Keeper) IsUnclaimedServiceOrigin(ctx sdk.Context, origin string) bool {
|
||||
rec, _ := k.OrmDB.ServiceRecordTable().GetByOriginUri(ctx, origin)
|
||||
rec, _ := k.OrmDB.ServiceRecordTable().GetByOrigin(ctx, origin)
|
||||
return rec == nil
|
||||
}
|
||||
|
||||
@@ -99,7 +99,7 @@ func (k Keeper) IsValidServiceOrigin(ctx sdk.Context, origin string, clientInfo
|
||||
if origin != clientInfo.Hostname {
|
||||
return false
|
||||
}
|
||||
rec, err := k.OrmDB.ServiceRecordTable().GetByOriginUri(ctx, origin)
|
||||
rec, err := k.OrmDB.ServiceRecordTable().GetByOrigin(ctx, origin)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
package keeper
|
||||
|
||||
import (
|
||||
didv1 "github.com/onsonr/sonr/api/did/v1"
|
||||
"github.com/onsonr/sonr/x/did/types"
|
||||
)
|
||||
|
||||
func convertServiceRecord(rec *didv1.ServiceRecord) *types.Service {
|
||||
return &types.Service{
|
||||
Origin: rec.OriginUri,
|
||||
}
|
||||
}
|
||||
+10
-40
@@ -2,11 +2,6 @@ package keeper
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"google.golang.org/genproto/googleapis/api/httpbody"
|
||||
"google.golang.org/grpc/peer"
|
||||
|
||||
"github.com/onsonr/sonr/x/did/types"
|
||||
)
|
||||
@@ -23,52 +18,27 @@ func NewQuerier(keeper Keeper) Querier {
|
||||
|
||||
// Params returns the total set of did parameters.
|
||||
func (k Querier) Params(
|
||||
c context.Context,
|
||||
goCtx context.Context,
|
||||
req *types.QueryRequest,
|
||||
) (*types.QueryParamsResponse, error) {
|
||||
ctx := sdk.UnwrapSDKContext(c)
|
||||
|
||||
p, err := k.Keeper.Params.Get(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
params := p.ActiveParams(k.HasIPFSConnection())
|
||||
return &types.QueryParamsResponse{Params: ¶ms}, nil
|
||||
) (*types.QueryResponse, error) {
|
||||
ctx := k.CurrentCtx(goCtx)
|
||||
return &types.QueryResponse{Params: k.GetParams(ctx.SDK())}, nil
|
||||
}
|
||||
|
||||
// Resolve implements types.QueryServer.
|
||||
func (k Querier) Resolve(
|
||||
goCtx context.Context,
|
||||
req *types.QueryRequest,
|
||||
) (*types.QueryResolveResponse, error) {
|
||||
// ctx := sdk.UnwrapSDKContext(goCtx)
|
||||
return &types.QueryResolveResponse{}, nil
|
||||
) (*types.QueryResponse, error) {
|
||||
ctx := k.CurrentCtx(goCtx)
|
||||
return &types.QueryResponse{Params: k.GetParams(ctx.SDK())}, nil
|
||||
}
|
||||
|
||||
// Service implements types.QueryServer.
|
||||
func (k Querier) Service(
|
||||
goCtx context.Context,
|
||||
req *types.QueryRequest,
|
||||
) (*types.QueryServiceResponse, error) {
|
||||
ctx := sdk.UnwrapSDKContext(goCtx)
|
||||
|
||||
_, ok := peer.FromContext(goCtx)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("failed to get peer from context")
|
||||
}
|
||||
|
||||
rec, err := k.OrmDB.ServiceRecordTable().GetByOriginUri(ctx, req.Origin)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &types.QueryServiceResponse{Service: convertServiceRecord(rec)}, nil
|
||||
}
|
||||
|
||||
// HTMX implements types.QueryServer.
|
||||
func (k Querier) HTMX(goCtx context.Context, req *types.QueryRequest) (*httpbody.HttpBody, error) {
|
||||
// ctx := sdk.UnwrapSDKContext(goCtx)
|
||||
return &httpbody.HttpBody{
|
||||
ContentType: "text/html",
|
||||
Data: []byte("<html><body>HTMX</body></html>"),
|
||||
}, nil
|
||||
) (*types.QueryResponse, error) {
|
||||
ctx := k.CurrentCtx(goCtx)
|
||||
return &types.QueryResponse{Service: ctx.GetServiceInfo(req.GetOrigin()), Params: ctx.Params()}, nil
|
||||
}
|
||||
|
||||
+30
-38
@@ -9,7 +9,7 @@ import (
|
||||
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
|
||||
|
||||
"github.com/onsonr/sonr/x/did/builder"
|
||||
"github.com/onsonr/sonr/x/did/middleware"
|
||||
snrctx "github.com/onsonr/sonr/x/did/context"
|
||||
"github.com/onsonr/sonr/x/did/types"
|
||||
)
|
||||
|
||||
@@ -24,38 +24,17 @@ func NewMsgServerImpl(keeper Keeper) types.MsgServer {
|
||||
return &msgServer{k: keeper}
|
||||
}
|
||||
|
||||
// UpdateParams updates the x/did module parameters.
|
||||
func (ms msgServer) UpdateParams(
|
||||
ctx context.Context,
|
||||
msg *types.MsgUpdateParams,
|
||||
) (*types.MsgUpdateParamsResponse, error) {
|
||||
if ms.k.authority != msg.Authority {
|
||||
// AuthorizeService implements types.MsgServer.
|
||||
func (ms msgServer) AuthorizeService(goCtx context.Context, msg *types.MsgAuthorizeService) (*types.MsgAuthorizeServiceResponse, error) {
|
||||
if ms.k.authority != msg.Controller {
|
||||
return nil, errors.Wrapf(
|
||||
govtypes.ErrInvalidSigner,
|
||||
"invalid authority; expected %s, got %s",
|
||||
ms.k.authority,
|
||||
msg.Authority,
|
||||
msg.Controller,
|
||||
)
|
||||
}
|
||||
|
||||
return nil, ms.k.Params.Set(ctx, msg.Params)
|
||||
}
|
||||
|
||||
// Authorize implements types.MsgServer.
|
||||
func (ms msgServer) Authorize(
|
||||
ctx context.Context,
|
||||
msg *types.MsgAuthorize,
|
||||
) (*types.MsgAuthorizeResponse, error) {
|
||||
if ms.k.authority != msg.Authority {
|
||||
return nil, errors.Wrapf(
|
||||
govtypes.ErrInvalidSigner,
|
||||
"invalid authority; expected %s, got %s",
|
||||
ms.k.authority,
|
||||
msg.Authority,
|
||||
)
|
||||
}
|
||||
// ctx := sdk.UnwrapSDKContext(goCtx)
|
||||
return &types.MsgAuthorizeResponse{}, nil
|
||||
return &types.MsgAuthorizeServiceResponse{}, nil
|
||||
}
|
||||
|
||||
// AllocateVault implements types.MsgServer.
|
||||
@@ -64,7 +43,7 @@ func (ms msgServer) AllocateVault(
|
||||
msg *types.MsgAllocateVault,
|
||||
) (*types.MsgAllocateVaultResponse, error) {
|
||||
ctx := sdk.UnwrapSDKContext(goCtx)
|
||||
clientInfo, err := middleware.ExtractClientInfo(goCtx)
|
||||
clientInfo, err := snrctx.ExtractClientInfo(goCtx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -79,7 +58,7 @@ func (ms msgServer) AllocateVault(
|
||||
return nil, err
|
||||
}
|
||||
|
||||
regOpts, err := builder.NewRegistrationOptions(msg.Origin, msg.Subject, cid, ms.k.GetParams(ctx))
|
||||
regOpts, err := builder.GetPublicKeyCredentialCreationOptions(msg.Origin, msg.Subject, cid, ms.k.GetParams(ctx))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -113,23 +92,36 @@ func (ms msgServer) RegisterService(
|
||||
) (*types.MsgRegisterServiceResponse, error) {
|
||||
ctx := sdk.UnwrapSDKContext(goCtx)
|
||||
|
||||
clientInfo, err := middleware.ExtractClientInfo(goCtx)
|
||||
clientInfo, err := snrctx.ExtractClientInfo(goCtx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 1.Check if the service origin is valid
|
||||
if !ms.k.IsValidServiceOrigin(ctx, msg.OriginUri, clientInfo) {
|
||||
if !ms.k.IsValidServiceOrigin(ctx, msg.Service.Origin, clientInfo) {
|
||||
return nil, types.ErrInvalidServiceOrigin
|
||||
}
|
||||
return ms.k.insertService(ctx, msg)
|
||||
return ms.k.insertService(ctx, msg.Service)
|
||||
}
|
||||
|
||||
// SyncVault implements types.MsgServer.
|
||||
func (ms msgServer) SyncVault(
|
||||
ctx context.Context,
|
||||
msg *types.MsgSyncVault,
|
||||
) (*types.MsgSyncVaultResponse, error) {
|
||||
// SyncController implements types.MsgServer.
|
||||
func (ms msgServer) SyncController(ctx context.Context, msg *types.MsgSyncController) (*types.MsgSyncControllerResponse, error) {
|
||||
// ctx := sdk.UnwrapSDKContext(goCtx)
|
||||
return &types.MsgSyncVaultResponse{}, nil
|
||||
return &types.MsgSyncControllerResponse{}, nil
|
||||
}
|
||||
|
||||
// UpdateParams updates the x/did module parameters.
|
||||
func (ms msgServer) UpdateParams(
|
||||
ctx context.Context,
|
||||
msg *types.MsgUpdateParams,
|
||||
) (*types.MsgUpdateParamsResponse, error) {
|
||||
if ms.k.authority != msg.Authority {
|
||||
return nil, errors.Wrapf(
|
||||
govtypes.ErrInvalidSigner,
|
||||
"invalid authority; expected %s, got %s",
|
||||
ms.k.authority,
|
||||
msg.Authority,
|
||||
)
|
||||
}
|
||||
return nil, ms.k.Params.Set(ctx, msg.Params)
|
||||
}
|
||||
|
||||
@@ -3,19 +3,17 @@ package keeper
|
||||
import (
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
|
||||
didv1 "github.com/onsonr/sonr/api/did/v1"
|
||||
"github.com/onsonr/sonr/x/did/builder"
|
||||
"github.com/onsonr/sonr/x/did/types"
|
||||
)
|
||||
|
||||
// insertService inserts a service record into the database
|
||||
func (k Keeper) insertService(
|
||||
ctx sdk.Context,
|
||||
svc *types.MsgRegisterService,
|
||||
svc *types.Service,
|
||||
) (*types.MsgRegisterServiceResponse, error) {
|
||||
record := didv1.ServiceRecord{
|
||||
Id: svc.OriginUri,
|
||||
}
|
||||
err := k.OrmDB.ServiceRecordTable().Insert(ctx, &record)
|
||||
record := builder.APIFormatServiceRecord(svc)
|
||||
err := k.OrmDB.ServiceRecordTable().Insert(ctx, record)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -1,12 +1,19 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
fmt "fmt"
|
||||
|
||||
"github.com/cosmos/btcutil/bech32"
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
"github.com/cosmos/cosmos-sdk/codec/types"
|
||||
cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec"
|
||||
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/types/msgservice"
|
||||
"github.com/mr-tron/base58/base58"
|
||||
"github.com/onsonr/crypto"
|
||||
// this line is used by starport scaffolding # 1
|
||||
)
|
||||
|
||||
@@ -41,3 +48,153 @@ func RegisterInterfaces(registry types.InterfaceRegistry) {
|
||||
)
|
||||
msgservice.RegisterMsgServiceDesc(registry, &_Msg_serviceDesc)
|
||||
}
|
||||
|
||||
type ChainCode uint32
|
||||
|
||||
const (
|
||||
ChainCodeBTC ChainCode = 0
|
||||
ChainCodeETH ChainCode = 60
|
||||
ChainCodeIBC ChainCode = 118
|
||||
ChainCodeSNR ChainCode = 703
|
||||
)
|
||||
|
||||
var InitialChainCodes = map[DIDNamespace]ChainCode{
|
||||
DIDNamespace_DID_NAMESPACE_BITCOIN: ChainCodeBTC,
|
||||
DIDNamespace_DID_NAMESPACE_IBC: ChainCodeIBC,
|
||||
DIDNamespace_DID_NAMESPACE_ETHEREUM: ChainCodeETH,
|
||||
DIDNamespace_DID_NAMESPACE_SONR: ChainCodeSNR,
|
||||
}
|
||||
|
||||
func (c ChainCode) FormatAddress(pubKey *PubKey) (string, error) {
|
||||
switch c {
|
||||
case ChainCodeBTC:
|
||||
return bech32.Encode("bc", pubKey.Bytes())
|
||||
|
||||
case ChainCodeETH:
|
||||
return bech32.Encode("eth", pubKey.Bytes())
|
||||
|
||||
case ChainCodeSNR:
|
||||
return bech32.Encode("idx", pubKey.Bytes())
|
||||
|
||||
case ChainCodeIBC:
|
||||
return bech32.Encode("cosmos", pubKey.Bytes())
|
||||
|
||||
}
|
||||
return "", ErrUnsopportedChainCode
|
||||
}
|
||||
|
||||
func (n DIDNamespace) ChainCode() (uint32, error) {
|
||||
switch n {
|
||||
case DIDNamespace_DID_NAMESPACE_BITCOIN:
|
||||
return 0, nil
|
||||
case DIDNamespace_DID_NAMESPACE_ETHEREUM:
|
||||
return 64, nil
|
||||
case DIDNamespace_DID_NAMESPACE_IBC:
|
||||
return 118, nil
|
||||
case DIDNamespace_DID_NAMESPACE_SONR:
|
||||
return 703, nil
|
||||
default:
|
||||
return 0, fmt.Errorf("unsupported chain")
|
||||
}
|
||||
}
|
||||
|
||||
func (n DIDNamespace) DIDMethod() string {
|
||||
switch n {
|
||||
case DIDNamespace_DID_NAMESPACE_IPFS:
|
||||
return "ipfs"
|
||||
case DIDNamespace_DID_NAMESPACE_SONR:
|
||||
return "sonr"
|
||||
case DIDNamespace_DID_NAMESPACE_BITCOIN:
|
||||
return "btcr"
|
||||
case DIDNamespace_DID_NAMESPACE_ETHEREUM:
|
||||
return "ethr"
|
||||
case DIDNamespace_DID_NAMESPACE_IBC:
|
||||
return "ibcr"
|
||||
case DIDNamespace_DID_NAMESPACE_WEBAUTHN:
|
||||
return "webauthn"
|
||||
case DIDNamespace_DID_NAMESPACE_DWN:
|
||||
return "motr"
|
||||
case DIDNamespace_DID_NAMESPACE_SERVICE:
|
||||
return "web"
|
||||
default:
|
||||
return "n/a"
|
||||
}
|
||||
}
|
||||
|
||||
func (n DIDNamespace) FormatDID(subject string) string {
|
||||
return fmt.Sprintf("%s:%s", n.DIDMethod(), subject)
|
||||
}
|
||||
|
||||
type EncodedKey []byte
|
||||
|
||||
func (e KeyEncoding) EncodeRaw(data []byte) (EncodedKey, error) {
|
||||
switch e {
|
||||
case KeyEncoding_KEY_ENCODING_RAW:
|
||||
return data, nil
|
||||
case KeyEncoding_KEY_ENCODING_HEX:
|
||||
return []byte(hex.EncodeToString(data)), nil
|
||||
case KeyEncoding_KEY_ENCODING_MULTIBASE:
|
||||
return []byte(base58.Encode(data)), nil
|
||||
default:
|
||||
return nil, nil
|
||||
}
|
||||
}
|
||||
|
||||
func (e KeyEncoding) DecodeRaw(data EncodedKey) ([]byte, error) {
|
||||
switch e {
|
||||
case KeyEncoding_KEY_ENCODING_RAW:
|
||||
return data, nil
|
||||
case KeyEncoding_KEY_ENCODING_HEX:
|
||||
return hex.DecodeString(string(data))
|
||||
case KeyEncoding_KEY_ENCODING_MULTIBASE:
|
||||
return base58.Decode(string(data))
|
||||
default:
|
||||
return nil, nil
|
||||
}
|
||||
}
|
||||
|
||||
type COSEAlgorithmIdentifier int
|
||||
|
||||
func (k KeyAlgorithm) CoseIdentifier() COSEAlgorithmIdentifier {
|
||||
switch k {
|
||||
case KeyAlgorithm_KEY_ALGORITHM_ES256:
|
||||
return COSEAlgorithmIdentifier(-7)
|
||||
case KeyAlgorithm_KEY_ALGORITHM_ES384:
|
||||
return COSEAlgorithmIdentifier(-35)
|
||||
case KeyAlgorithm_KEY_ALGORITHM_ES512:
|
||||
return COSEAlgorithmIdentifier(-36)
|
||||
case KeyAlgorithm_KEY_ALGORITHM_EDDSA:
|
||||
return COSEAlgorithmIdentifier(-8)
|
||||
case KeyAlgorithm_KEY_ALGORITHM_ES256K:
|
||||
return COSEAlgorithmIdentifier(-10)
|
||||
default:
|
||||
return COSEAlgorithmIdentifier(0)
|
||||
}
|
||||
}
|
||||
|
||||
func (k KeyCurve) ComputePublicKey(data []byte) (*PubKey, error) {
|
||||
return nil, ErrUnsupportedKeyCurve
|
||||
}
|
||||
|
||||
func (k *Keyshare) Equals(o crypto.MPCShare) bool {
|
||||
opk := o.GetPublicKey()
|
||||
if opk != nil && k.PublicKey == nil {
|
||||
return false
|
||||
}
|
||||
return k.GetRole() == o.GetRole()
|
||||
}
|
||||
|
||||
func (k *Keyshare) IsUser() bool {
|
||||
return k.Role == 2
|
||||
}
|
||||
|
||||
func (k *Keyshare) IsValidator() bool {
|
||||
return k.Role == 1
|
||||
}
|
||||
|
||||
// ComputeOriginTXTRecord generates a fingerprint for a given origin
|
||||
func ComputeOriginTXTRecord(origin string) string {
|
||||
h := sha256.New()
|
||||
h.Write([]byte(origin))
|
||||
return fmt.Sprintf("v=sonr,o=%s,p=%x", origin, h.Sum(nil))
|
||||
}
|
||||
|
||||
@@ -1,136 +0,0 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
fmt "fmt"
|
||||
|
||||
"github.com/cosmos/btcutil/bech32"
|
||||
"github.com/mr-tron/base58/base58"
|
||||
)
|
||||
|
||||
type ChainCode uint32
|
||||
|
||||
const (
|
||||
ChainCodeBTC ChainCode = 0
|
||||
ChainCodeETH ChainCode = 60
|
||||
ChainCodeIBC ChainCode = 118
|
||||
ChainCodeSNR ChainCode = 703
|
||||
)
|
||||
|
||||
var InitialChainCodes = map[DIDNamespace]ChainCode{
|
||||
DIDNamespace_DID_NAMESPACE_BITCOIN: ChainCodeBTC,
|
||||
DIDNamespace_DID_NAMESPACE_IBC: ChainCodeIBC,
|
||||
DIDNamespace_DID_NAMESPACE_ETHEREUM: ChainCodeETH,
|
||||
DIDNamespace_DID_NAMESPACE_SONR: ChainCodeSNR,
|
||||
}
|
||||
|
||||
func (c ChainCode) FormatAddress(pubKey *PubKey) (string, error) {
|
||||
switch c {
|
||||
case ChainCodeBTC:
|
||||
return bech32.Encode("bc", pubKey.Bytes())
|
||||
|
||||
case ChainCodeETH:
|
||||
return bech32.Encode("eth", pubKey.Bytes())
|
||||
|
||||
case ChainCodeSNR:
|
||||
return bech32.Encode("idx", pubKey.Bytes())
|
||||
|
||||
case ChainCodeIBC:
|
||||
return bech32.Encode("cosmos", pubKey.Bytes())
|
||||
|
||||
}
|
||||
return "", ErrUnsopportedChainCode
|
||||
}
|
||||
|
||||
func (n DIDNamespace) ChainCode() (uint32, error) {
|
||||
switch n {
|
||||
case DIDNamespace_DID_NAMESPACE_BITCOIN:
|
||||
return 0, nil
|
||||
case DIDNamespace_DID_NAMESPACE_ETHEREUM:
|
||||
return 64, nil
|
||||
case DIDNamespace_DID_NAMESPACE_IBC:
|
||||
return 118, nil
|
||||
case DIDNamespace_DID_NAMESPACE_SONR:
|
||||
return 703, nil
|
||||
default:
|
||||
return 0, fmt.Errorf("unsupported chain")
|
||||
}
|
||||
}
|
||||
|
||||
func (n DIDNamespace) DIDMethod() string {
|
||||
switch n {
|
||||
case DIDNamespace_DID_NAMESPACE_IPFS:
|
||||
return "ipfs"
|
||||
case DIDNamespace_DID_NAMESPACE_SONR:
|
||||
return "sonr"
|
||||
case DIDNamespace_DID_NAMESPACE_BITCOIN:
|
||||
return "btcr"
|
||||
case DIDNamespace_DID_NAMESPACE_ETHEREUM:
|
||||
return "ethr"
|
||||
case DIDNamespace_DID_NAMESPACE_IBC:
|
||||
return "ibcr"
|
||||
case DIDNamespace_DID_NAMESPACE_WEBAUTHN:
|
||||
return "webauthn"
|
||||
case DIDNamespace_DID_NAMESPACE_DWN:
|
||||
return "motr"
|
||||
case DIDNamespace_DID_NAMESPACE_SERVICE:
|
||||
return "web"
|
||||
default:
|
||||
return "n/a"
|
||||
}
|
||||
}
|
||||
|
||||
func (n DIDNamespace) FormatDID(subject string) string {
|
||||
return fmt.Sprintf("%s:%s", n.DIDMethod(), subject)
|
||||
}
|
||||
|
||||
type EncodedKey []byte
|
||||
|
||||
func (e KeyEncoding) EncodeRaw(data []byte) (EncodedKey, error) {
|
||||
switch e {
|
||||
case KeyEncoding_KEY_ENCODING_RAW:
|
||||
return data, nil
|
||||
case KeyEncoding_KEY_ENCODING_HEX:
|
||||
return []byte(hex.EncodeToString(data)), nil
|
||||
case KeyEncoding_KEY_ENCODING_MULTIBASE:
|
||||
return []byte(base58.Encode(data)), nil
|
||||
default:
|
||||
return nil, nil
|
||||
}
|
||||
}
|
||||
|
||||
func (e KeyEncoding) DecodeRaw(data EncodedKey) ([]byte, error) {
|
||||
switch e {
|
||||
case KeyEncoding_KEY_ENCODING_RAW:
|
||||
return data, nil
|
||||
case KeyEncoding_KEY_ENCODING_HEX:
|
||||
return hex.DecodeString(string(data))
|
||||
case KeyEncoding_KEY_ENCODING_MULTIBASE:
|
||||
return base58.Decode(string(data))
|
||||
default:
|
||||
return nil, nil
|
||||
}
|
||||
}
|
||||
|
||||
type COSEAlgorithmIdentifier int
|
||||
|
||||
func (k KeyAlgorithm) CoseIdentifier() COSEAlgorithmIdentifier {
|
||||
switch k {
|
||||
case KeyAlgorithm_KEY_ALGORITHM_ES256:
|
||||
return COSEAlgorithmIdentifier(-7)
|
||||
case KeyAlgorithm_KEY_ALGORITHM_ES384:
|
||||
return COSEAlgorithmIdentifier(-35)
|
||||
case KeyAlgorithm_KEY_ALGORITHM_ES512:
|
||||
return COSEAlgorithmIdentifier(-36)
|
||||
case KeyAlgorithm_KEY_ALGORITHM_EDDSA:
|
||||
return COSEAlgorithmIdentifier(-8)
|
||||
case KeyAlgorithm_KEY_ALGORITHM_ES256K:
|
||||
return COSEAlgorithmIdentifier(-10)
|
||||
default:
|
||||
return COSEAlgorithmIdentifier(0)
|
||||
}
|
||||
}
|
||||
|
||||
func (k KeyCurve) ComputePublicKey(data []byte) (*PubKey, error) {
|
||||
return nil, ErrUnsupportedKeyCurve
|
||||
}
|
||||
@@ -7,9 +7,11 @@ var (
|
||||
ErrInvalidETHAddressFormat = sdkerrors.Register(ModuleName, 200, "invalid ETH address format")
|
||||
ErrInvalidBTCAddressFormat = sdkerrors.Register(ModuleName, 201, "invalid BTC address format")
|
||||
ErrInvalidIDXAddressFormat = sdkerrors.Register(ModuleName, 202, "invalid IDX address format")
|
||||
ErrInvalidOriginFormat = sdkerrors.Register(ModuleName, 203, "invalid origin format")
|
||||
ErrInvalidServiceOrigin = sdkerrors.Register(ModuleName, 300, "invalid service origin")
|
||||
ErrUnrecognizedService = sdkerrors.Register(ModuleName, 301, "unrecognized service")
|
||||
ErrUnsupportedKeyEncoding = sdkerrors.Register(ModuleName, 400, "unsupported key encoding")
|
||||
ErrUnsopportedChainCode = sdkerrors.Register(ModuleName, 401, "unsupported chain code")
|
||||
ErrUnsupportedKeyCurve = sdkerrors.Register(ModuleName, 402, "unsupported key curve")
|
||||
ErrInvalidSignature = sdkerrors.Register(ModuleName, 403, "invalid signature")
|
||||
)
|
||||
|
||||
+36
-16
@@ -53,7 +53,6 @@ func DefaultParams() Params {
|
||||
WhitelistedAssets: DefaultAssets(),
|
||||
WhitelistedChains: DefaultChains(),
|
||||
AllowedPublicKeys: DefaultKeyInfos(),
|
||||
OpenidConfig: DefaultOpenIDConfig(),
|
||||
LocalhostRegistrationEnabled: true,
|
||||
ConveyancePreference: "direct",
|
||||
AttestationFormats: []string{"packed", "android-key", "fido-u2f", "apple"},
|
||||
@@ -163,21 +162,6 @@ func DefaultKeyInfos() []*KeyInfo {
|
||||
}
|
||||
}
|
||||
|
||||
func DefaultOpenIDConfig() *OpenIDConfig {
|
||||
return &OpenIDConfig{
|
||||
Issuer: "https://sonr.id",
|
||||
AuthorizationEndpoint: "https://api.sonr.id/auth",
|
||||
TokenEndpoint: "https://api.sonr.id/token",
|
||||
UserinfoEndpoint: "https://api.sonr.id/userinfo",
|
||||
ScopesSupported: []string{"openid", "profile", "email", "web3", "sonr"},
|
||||
ResponseTypesSupported: []string{"code"},
|
||||
ResponseModesSupported: []string{"query", "form_post"},
|
||||
GrantTypesSupported: []string{"authorization_code", "refresh_token"},
|
||||
AcrValuesSupported: []string{"passkey"},
|
||||
SubjectTypesSupported: []string{"public"},
|
||||
}
|
||||
}
|
||||
|
||||
func (p Params) ActiveParams(ipfsActive bool) Params {
|
||||
p.IpfsActive = ipfsActive
|
||||
return p
|
||||
@@ -198,3 +182,39 @@ func (p Params) Validate() error {
|
||||
// TODO:
|
||||
return nil
|
||||
}
|
||||
|
||||
//
|
||||
// # Genesis Structures
|
||||
//
|
||||
|
||||
// Equal returns true if two asset infos are equal
|
||||
func (a *AssetInfo) Equal(b *AssetInfo) bool {
|
||||
if a == nil && b == nil {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Equal returns true if two chain infos are equal
|
||||
func (c *ChainInfo) Equal(b *ChainInfo) bool {
|
||||
if c == nil && b == nil {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Equal returns true if two key infos are equal
|
||||
func (k *KeyInfo) Equal(b *KeyInfo) bool {
|
||||
if k == nil && b == nil {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Equal returns true if two validator infos are equal
|
||||
func (v *ValidatorInfo) Equal(b *ValidatorInfo) bool {
|
||||
if v == nil && b == nil {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
+161
-861
File diff suppressed because it is too large
Load Diff
@@ -1,137 +0,0 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
|
||||
"github.com/mr-tron/base58/base58"
|
||||
)
|
||||
|
||||
//
|
||||
// # Genesis Structures
|
||||
//
|
||||
|
||||
// Equal returns true if two asset infos are equal
|
||||
func (a *AssetInfo) Equal(b *AssetInfo) bool {
|
||||
if a == nil && b == nil {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Equal returns true if two chain infos are equal
|
||||
func (c *ChainInfo) Equal(b *ChainInfo) bool {
|
||||
if c == nil && b == nil {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Equal returns true if two OpenID config infos are equal
|
||||
func (o *OpenIDConfig) Equal(b *OpenIDConfig) bool {
|
||||
if o == nil && b == nil {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Equal returns true if two key infos are equal
|
||||
func (k *KeyInfo) Equal(b *KeyInfo) bool {
|
||||
if k == nil && b == nil {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Equal returns true if two validator infos are equal
|
||||
func (v *ValidatorInfo) Equal(b *ValidatorInfo) bool {
|
||||
if v == nil && b == nil {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// DecodePublicKey extracts the public key from the given data
|
||||
func (k *KeyInfo) DecodePublicKey(data interface{}) ([]byte, error) {
|
||||
var bz []byte
|
||||
switch v := data.(type) {
|
||||
case string:
|
||||
bz = []byte(v)
|
||||
case []byte:
|
||||
bz = v
|
||||
default:
|
||||
return nil, ErrUnsupportedKeyEncoding
|
||||
}
|
||||
|
||||
if k.Encoding == KeyEncoding_KEY_ENCODING_RAW {
|
||||
return bz, nil
|
||||
}
|
||||
if k.Encoding == KeyEncoding_KEY_ENCODING_HEX {
|
||||
return hex.DecodeString(string(bz))
|
||||
}
|
||||
if k.Encoding == KeyEncoding_KEY_ENCODING_MULTIBASE {
|
||||
return base58.Decode(string(bz))
|
||||
}
|
||||
return nil, ErrUnsupportedKeyEncoding
|
||||
}
|
||||
|
||||
// EncodePublicKey encodes the public key according to the KeyInfo's encoding
|
||||
func (k *KeyInfo) EncodePublicKey(data []byte) (string, error) {
|
||||
if k.Encoding == KeyEncoding_KEY_ENCODING_RAW {
|
||||
return string(data), nil
|
||||
}
|
||||
if k.Encoding == KeyEncoding_KEY_ENCODING_HEX {
|
||||
return hex.EncodeToString(data), nil
|
||||
}
|
||||
if k.Encoding == KeyEncoding_KEY_ENCODING_MULTIBASE {
|
||||
return base58.Encode(data), nil
|
||||
}
|
||||
return "", ErrUnsupportedKeyEncoding
|
||||
}
|
||||
|
||||
// DiscoveryDocument represents the OIDC discovery document.
|
||||
type DiscoveryDocument struct {
|
||||
Issuer string `json:"issuer"`
|
||||
AuthorizationEndpoint string `json:"authorization_endpoint"`
|
||||
TokenEndpoint string `json:"token_endpoint"`
|
||||
UserinfoEndpoint string `json:"userinfo_endpoint"`
|
||||
JwksURI string `json:"jwks_uri"`
|
||||
RegistrationEndpoint string `json:"registration_endpoint"`
|
||||
ScopesSupported []string `json:"scopes_supported"`
|
||||
ResponseTypesSupported []string `json:"response_types_supported"`
|
||||
SubjectTypesSupported []string `json:"subject_types_supported"`
|
||||
IDTokenSigningAlgValuesSupported []string `json:"id_token_signing_alg_values_supported"`
|
||||
ClaimsSupported []string `json:"claims_supported"`
|
||||
GrantTypesSupported []string `json:"grant_types_supported"`
|
||||
TokenEndpointAuthMethodsSupported []string `json:"token_endpoint_auth_methods_supported"`
|
||||
}
|
||||
|
||||
var WalletKeyInfo = &KeyInfo{
|
||||
Role: KeyRole_KEY_ROLE_DELEGATION,
|
||||
Curve: KeyCurve_KEY_CURVE_SECP256K1,
|
||||
Algorithm: KeyAlgorithm_KEY_ALGORITHM_ECDSA,
|
||||
Encoding: KeyEncoding_KEY_ENCODING_HEX,
|
||||
Type: KeyType_KEY_TYPE_BIP32,
|
||||
}
|
||||
|
||||
var EthKeyInfo = &KeyInfo{
|
||||
Role: KeyRole_KEY_ROLE_DELEGATION,
|
||||
Curve: KeyCurve_KEY_CURVE_KECCAK256,
|
||||
Algorithm: KeyAlgorithm_KEY_ALGORITHM_ECDSA,
|
||||
Encoding: KeyEncoding_KEY_ENCODING_HEX,
|
||||
Type: KeyType_KEY_TYPE_BIP32,
|
||||
}
|
||||
|
||||
var SonrKeyInfo = &KeyInfo{
|
||||
Role: KeyRole_KEY_ROLE_INVOCATION,
|
||||
Curve: KeyCurve_KEY_CURVE_P256,
|
||||
Algorithm: KeyAlgorithm_KEY_ALGORITHM_ECDSA,
|
||||
Encoding: KeyEncoding_KEY_ENCODING_HEX,
|
||||
Type: KeyType_KEY_TYPE_MPC,
|
||||
}
|
||||
|
||||
var ChainCodeKeyInfos = map[ChainCode]*KeyInfo{
|
||||
ChainCodeBTC: WalletKeyInfo,
|
||||
ChainCodeETH: EthKeyInfo,
|
||||
ChainCodeSNR: SonrKeyInfo,
|
||||
ChainCodeIBC: WalletKeyInfo,
|
||||
}
|
||||
+2135
-2682
File diff suppressed because it is too large
Load Diff
+68
-41
@@ -1,15 +1,44 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
fmt "fmt"
|
||||
"math/big"
|
||||
"encoding/hex"
|
||||
|
||||
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
|
||||
"github.com/onsonr/crypto/core/curves"
|
||||
"github.com/onsonr/crypto/signatures/ecdsa"
|
||||
"golang.org/x/crypto/sha3"
|
||||
"github.com/mr-tron/base58/base58"
|
||||
"github.com/onsonr/crypto"
|
||||
)
|
||||
|
||||
var WalletKeyInfo = &KeyInfo{
|
||||
Role: KeyRole_KEY_ROLE_DELEGATION,
|
||||
Curve: KeyCurve_KEY_CURVE_SECP256K1,
|
||||
Algorithm: KeyAlgorithm_KEY_ALGORITHM_ECDSA,
|
||||
Encoding: KeyEncoding_KEY_ENCODING_HEX,
|
||||
Type: KeyType_KEY_TYPE_BIP32,
|
||||
}
|
||||
|
||||
var EthKeyInfo = &KeyInfo{
|
||||
Role: KeyRole_KEY_ROLE_DELEGATION,
|
||||
Curve: KeyCurve_KEY_CURVE_KECCAK256,
|
||||
Algorithm: KeyAlgorithm_KEY_ALGORITHM_ECDSA,
|
||||
Encoding: KeyEncoding_KEY_ENCODING_HEX,
|
||||
Type: KeyType_KEY_TYPE_BIP32,
|
||||
}
|
||||
|
||||
var SonrKeyInfo = &KeyInfo{
|
||||
Role: KeyRole_KEY_ROLE_INVOCATION,
|
||||
Curve: KeyCurve_KEY_CURVE_P256,
|
||||
Algorithm: KeyAlgorithm_KEY_ALGORITHM_ECDSA,
|
||||
Encoding: KeyEncoding_KEY_ENCODING_HEX,
|
||||
Type: KeyType_KEY_TYPE_MPC,
|
||||
}
|
||||
|
||||
var ChainCodeKeyInfos = map[ChainCode]*KeyInfo{
|
||||
ChainCodeBTC: WalletKeyInfo,
|
||||
ChainCodeETH: EthKeyInfo,
|
||||
ChainCodeSNR: SonrKeyInfo,
|
||||
ChainCodeIBC: WalletKeyInfo,
|
||||
}
|
||||
|
||||
// NewEthPublicKey returns a new ethereum public key
|
||||
func NewPublicKey(data []byte, keyInfo *KeyInfo) (*PubKey, error) {
|
||||
encKey, err := keyInfo.Encoding.EncodeRaw(data)
|
||||
@@ -52,21 +81,12 @@ func (k *PubKey) Clone() cryptotypes.PubKey {
|
||||
|
||||
// VerifySignature verifies a signature over the given message
|
||||
func (k *PubKey) VerifySignature(msg []byte, sig []byte) bool {
|
||||
pp, err := buildEcPoint(k.Bytes())
|
||||
pk, err := crypto.ComputeEcdsaPublicKey(k.Bytes())
|
||||
sigMpc, err := crypto.DeserializeMPCSignature(sig)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
sigEd, err := ecdsa.DeserializeSecp256k1Signature(sig)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
hash := sha3.New256()
|
||||
_, err = hash.Write(msg)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
digest := hash.Sum(nil)
|
||||
return curves.VerifyEcdsa(pp, digest[:], sigEd)
|
||||
return crypto.VerifyMPCSignature(sigMpc, msg, pk)
|
||||
}
|
||||
|
||||
// Equals returns true if two public keys are equal
|
||||
@@ -79,36 +99,43 @@ func (k *PubKey) Equals(k2 cryptotypes.PubKey) bool {
|
||||
|
||||
// Type returns the type of the public key
|
||||
func (k *PubKey) Type() string {
|
||||
return ""
|
||||
return k.KeyType.String()
|
||||
}
|
||||
|
||||
// VerifySignature verifies the signature of a message
|
||||
func VerifySignature(key []byte, msg []byte, sig []byte) bool {
|
||||
pp, err := buildEcPoint(key)
|
||||
if err != nil {
|
||||
return false
|
||||
// DecodePublicKey extracts the public key from the given data
|
||||
func (k *KeyInfo) DecodePublicKey(data interface{}) ([]byte, error) {
|
||||
var bz []byte
|
||||
switch v := data.(type) {
|
||||
case string:
|
||||
bz = []byte(v)
|
||||
case []byte:
|
||||
bz = v
|
||||
default:
|
||||
return nil, ErrUnsupportedKeyEncoding
|
||||
}
|
||||
sigEd, err := ecdsa.DeserializeSecp256k1Signature(sig)
|
||||
if err != nil {
|
||||
return false
|
||||
|
||||
if k.Encoding == KeyEncoding_KEY_ENCODING_RAW {
|
||||
return bz, nil
|
||||
}
|
||||
hash := sha3.New256()
|
||||
_, err = hash.Write(msg)
|
||||
if err != nil {
|
||||
return false
|
||||
if k.Encoding == KeyEncoding_KEY_ENCODING_HEX {
|
||||
return hex.DecodeString(string(bz))
|
||||
}
|
||||
digest := hash.Sum(nil)
|
||||
return curves.VerifyEcdsa(pp, digest[:], sigEd)
|
||||
if k.Encoding == KeyEncoding_KEY_ENCODING_MULTIBASE {
|
||||
return base58.Decode(string(bz))
|
||||
}
|
||||
return nil, ErrUnsupportedKeyEncoding
|
||||
}
|
||||
|
||||
// BuildEcPoint builds an elliptic curve point from a compressed byte slice
|
||||
func buildEcPoint(pubKey []byte) (*curves.EcPoint, error) {
|
||||
crv := curves.K256()
|
||||
x := new(big.Int).SetBytes(pubKey[1:33])
|
||||
y := new(big.Int).SetBytes(pubKey[33:])
|
||||
ecCurve, err := crv.ToEllipticCurve()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error converting curve: %v", err)
|
||||
// EncodePublicKey encodes the public key according to the KeyInfo's encoding
|
||||
func (k *KeyInfo) EncodePublicKey(data []byte) (string, error) {
|
||||
if k.Encoding == KeyEncoding_KEY_ENCODING_RAW {
|
||||
return string(data), nil
|
||||
}
|
||||
return &curves.EcPoint{X: x, Y: y, Curve: ecCurve}, nil
|
||||
if k.Encoding == KeyEncoding_KEY_ENCODING_HEX {
|
||||
return hex.EncodeToString(data), nil
|
||||
}
|
||||
if k.Encoding == KeyEncoding_KEY_ENCODING_MULTIBASE {
|
||||
return base58.Encode(data), nil
|
||||
}
|
||||
return "", ErrUnsupportedKeyEncoding
|
||||
}
|
||||
|
||||
+72
-1597
File diff suppressed because it is too large
Load Diff
@@ -1,28 +0,0 @@
|
||||
package types
|
||||
|
||||
import didv1 "github.com/onsonr/sonr/api/did/v1"
|
||||
|
||||
func (m *MsgRegisterService) ExtractServiceRecord() (*didv1.ServiceRecord, error) {
|
||||
return &didv1.ServiceRecord{
|
||||
Controller: m.Controller,
|
||||
OriginUri: m.OriginUri,
|
||||
Description: m.Description,
|
||||
Permissions: convertPermissions(m.GetScopes()),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func convertPermissions(permissions *Permissions) *didv1.Permissions {
|
||||
if permissions == nil {
|
||||
return nil
|
||||
}
|
||||
return &didv1.Permissions{}
|
||||
}
|
||||
|
||||
// UserInfo represents the user information.
|
||||
type UserInfo struct {
|
||||
DID string `json:"did"`
|
||||
Sub string `json:"sub"`
|
||||
Name string `json:"name"`
|
||||
Email string `json:"email"`
|
||||
// Add other claims as needed
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
package types
|
||||
|
||||
// ByteArray is a list of byte arrays
|
||||
type ByteArray = [][]byte
|
||||
|
||||
// ToVerificationMethod converts a Profile to a VerificationMethod
|
||||
func (p Profile) ToVerificationMethod() VerificationMethod {
|
||||
return VerificationMethod{
|
||||
Id: p.Id,
|
||||
Controller: p.Controller,
|
||||
}
|
||||
}
|
||||
+736
-957
File diff suppressed because it is too large
Load Diff
+346
-752
File diff suppressed because it is too large
Load Diff
@@ -1,66 +0,0 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"crypto/hmac"
|
||||
"crypto/sha512"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"math/big"
|
||||
|
||||
"github.com/btcsuite/btcd/btcec/v2"
|
||||
)
|
||||
|
||||
// ComputeAccountPublicKey computes the public key of a child key given the extended public key, chain code, and index.
|
||||
func ComputeAccountPublicKey(extPubKey []byte, chainCode uint32, index int) ([]byte, error) {
|
||||
// Check if the index is a hardened child key
|
||||
if chainCode&0x80000000 != 0 && index < 0 {
|
||||
return nil, errors.New("invalid index")
|
||||
}
|
||||
|
||||
// Serialize the public key
|
||||
pubKey, err := btcec.ParsePubKey(extPubKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pubKeyBytes := pubKey.SerializeCompressed()
|
||||
|
||||
// Serialize the index
|
||||
indexBytes := make([]byte, 4)
|
||||
binary.BigEndian.PutUint32(indexBytes, uint32(index))
|
||||
|
||||
// Compute the HMAC-SHA512
|
||||
mac := hmac.New(sha512.New, []byte{byte(chainCode)})
|
||||
mac.Write(pubKeyBytes)
|
||||
mac.Write(indexBytes)
|
||||
I := mac.Sum(nil)
|
||||
|
||||
// Split I into two 32-byte sequences
|
||||
IL := I[:32]
|
||||
|
||||
// Convert IL to a big integer
|
||||
ilNum := new(big.Int).SetBytes(IL)
|
||||
|
||||
// Check if parse256(IL) >= n
|
||||
curve := btcec.S256()
|
||||
if ilNum.Cmp(curve.N) >= 0 {
|
||||
return nil, errors.New("invalid child key")
|
||||
}
|
||||
|
||||
// Compute the child public key
|
||||
ilx, ily := curve.ScalarBaseMult(IL)
|
||||
childX, childY := curve.Add(ilx, ily, pubKey.X(), pubKey.Y())
|
||||
lx := newBigIntFieldVal(childX)
|
||||
ly := newBigIntFieldVal(childY)
|
||||
|
||||
// Create the child public key
|
||||
childPubKey := btcec.NewPublicKey(lx, ly)
|
||||
childPubKeyBytes := childPubKey.SerializeCompressed()
|
||||
return childPubKeyBytes, nil
|
||||
}
|
||||
|
||||
// newBigIntFieldVal creates a new field value from a big integer.
|
||||
func newBigIntFieldVal(val *big.Int) *btcec.FieldVal {
|
||||
lx := new(btcec.FieldVal)
|
||||
lx.SetByteSlice(val.Bytes())
|
||||
return lx
|
||||
}
|
||||
+44
-31
@@ -7,12 +7,18 @@ import (
|
||||
"github.com/onsonr/crypto/core/curves"
|
||||
)
|
||||
|
||||
// Accumulator is the accumulator for the ZKP
|
||||
type Accumulator []byte
|
||||
|
||||
// Element is the element for the BLS scheme
|
||||
type Element = accumulator.Element
|
||||
|
||||
// NewProperty creates a new Property which is used for ZKP
|
||||
func NewProperty(propertyKey string, pubKey []byte) (*Property, error) {
|
||||
input := append(pubKey, []byte(propertyKey)...)
|
||||
// Witness is the witness for the ZKP
|
||||
type Witness []byte
|
||||
|
||||
// NewProof creates a new Proof which is used for ZKP
|
||||
func NewProof(id, controller, issuer, property string, pubKey []byte) (*Proof, error) {
|
||||
input := append(pubKey, []byte(property)...)
|
||||
hash := []byte(input)
|
||||
|
||||
curve := curves.BLS12381(&curves.PointBls12381G1{})
|
||||
@@ -26,47 +32,54 @@ func NewProperty(propertyKey string, pubKey []byte) (*Property, error) {
|
||||
return nil, fmt.Errorf("failed to marshal secret key: %w", err)
|
||||
}
|
||||
|
||||
return &Property{Key: keyBytes}, nil
|
||||
return &Proof{
|
||||
Id: id,
|
||||
Controller: controller,
|
||||
Issuer: issuer,
|
||||
Property: property,
|
||||
Accumulator: keyBytes,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// CreateAccumulator creates a new accumulator
|
||||
func CreateAccumulator(prop *Property, values ...string) (*Accumulator, error) {
|
||||
// CreateAccumulator creates a new accumulator for a Proof
|
||||
func CreateAccumulator(proof *Proof, values ...string) error {
|
||||
curve := curves.BLS12381(&curves.PointBls12381G1{})
|
||||
acc, err := new(accumulator.Accumulator).New(curve)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
|
||||
secretKey := new(accumulator.SecretKey)
|
||||
if err := secretKey.UnmarshalBinary(prop.Key); err != nil {
|
||||
return nil, err
|
||||
if err := secretKey.UnmarshalBinary(proof.Accumulator); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fin, _, err := acc.Update(secretKey, ConvertValuesToZeroKnowledgeElements(values), nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
|
||||
accBytes, err := fin.MarshalBinary()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to marshal accumulator: %w", err)
|
||||
return fmt.Errorf("failed to marshal accumulator: %w", err)
|
||||
}
|
||||
|
||||
return &Accumulator{Accumulator: accBytes}, nil
|
||||
proof.Accumulator = accBytes
|
||||
return nil
|
||||
}
|
||||
|
||||
// CreateWitness creates a witness for the accumulator for a given value
|
||||
func CreateWitness(prop *Property, acc *Accumulator, value string) (*Witness, error) {
|
||||
// CreateWitness creates a witness for the accumulator in a Proof for a given value
|
||||
func CreateWitness(proof *Proof, value string) ([]byte, error) {
|
||||
curve := curves.BLS12381(&curves.PointBls12381G1{})
|
||||
element := curve.Scalar.Hash([]byte(value))
|
||||
|
||||
secretKey := new(accumulator.SecretKey)
|
||||
if err := secretKey.UnmarshalBinary(prop.Key); err != nil {
|
||||
if err := secretKey.UnmarshalBinary(proof.Accumulator); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
accObj := new(accumulator.Accumulator)
|
||||
if err := accObj.UnmarshalBinary(acc.Accumulator); err != nil {
|
||||
if err := accObj.UnmarshalBinary(proof.Accumulator); err != nil {
|
||||
return nil, fmt.Errorf("failed to unmarshal accumulator: %w", err)
|
||||
}
|
||||
|
||||
@@ -79,14 +92,13 @@ func CreateWitness(prop *Property, acc *Accumulator, value string) (*Witness, er
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to marshal witness: %w", err)
|
||||
}
|
||||
|
||||
return &Witness{Witness: witnessBytes}, nil
|
||||
return witnessBytes, nil
|
||||
}
|
||||
|
||||
// VerifyWitness proves that a value is a member of the accumulator
|
||||
func VerifyWitness(prop *Property, acc *Accumulator, witness *Witness) error {
|
||||
func VerifyWitness(proof *Proof, acc Accumulator, witness Witness) error {
|
||||
secretKey := new(accumulator.SecretKey)
|
||||
if err := secretKey.UnmarshalBinary(prop.Key); err != nil {
|
||||
if err := secretKey.UnmarshalBinary([]byte(proof.Id)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -97,41 +109,42 @@ func VerifyWitness(prop *Property, acc *Accumulator, witness *Witness) error {
|
||||
}
|
||||
|
||||
accObj := new(accumulator.Accumulator)
|
||||
if err := accObj.UnmarshalBinary(acc.Accumulator); err != nil {
|
||||
if err := accObj.UnmarshalBinary(proof.Accumulator); err != nil {
|
||||
return fmt.Errorf("failed to unmarshal accumulator: %w", err)
|
||||
}
|
||||
|
||||
witnessObj := new(accumulator.MembershipWitness)
|
||||
if err := witnessObj.UnmarshalBinary(witness.Witness); err != nil {
|
||||
if err := witnessObj.UnmarshalBinary(witness); err != nil {
|
||||
return fmt.Errorf("failed to unmarshal witness: %w", err)
|
||||
}
|
||||
|
||||
return witnessObj.Verify(publicKey, accObj)
|
||||
}
|
||||
|
||||
// UpdateAccumulator updates the accumulator with new values
|
||||
func UpdateAccumulator(prop *Property, acc *Accumulator, addValues []string, removeValues []string) (*Accumulator, error) {
|
||||
// UpdateAccumulator updates the accumulator in a Proof with new values
|
||||
func UpdateAccumulator(proof *Proof, addValues []string, removeValues []string) error {
|
||||
secretKey := new(accumulator.SecretKey)
|
||||
if err := secretKey.UnmarshalBinary(prop.Key); err != nil {
|
||||
return nil, err
|
||||
if err := secretKey.UnmarshalBinary(proof.Accumulator); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
accObj := new(accumulator.Accumulator)
|
||||
if err := accObj.UnmarshalBinary(acc.Accumulator); err != nil {
|
||||
return nil, fmt.Errorf("failed to unmarshal accumulator: %w", err)
|
||||
if err := accObj.UnmarshalBinary(proof.Accumulator); err != nil {
|
||||
return fmt.Errorf("failed to unmarshal accumulator: %w", err)
|
||||
}
|
||||
|
||||
updatedAcc, _, err := accObj.Update(secretKey, ConvertValuesToZeroKnowledgeElements(addValues), ConvertValuesToZeroKnowledgeElements(removeValues))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
|
||||
updatedAccBytes, err := updatedAcc.MarshalBinary()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to marshal updated accumulator: %w", err)
|
||||
return fmt.Errorf("failed to marshal updated accumulator: %w", err)
|
||||
}
|
||||
|
||||
return &Accumulator{Accumulator: updatedAccBytes}, nil
|
||||
proof.Accumulator = updatedAccBytes
|
||||
return nil
|
||||
}
|
||||
|
||||
// ConvertValuesToZeroKnowledgeElements converts a slice of strings to a slice of accumulator elements
|
||||
|
||||
Reference in New Issue
Block a user