hypersign-protocol / whitepaper

2 stars 0 forks source link

HID-Dev v0.0.1 #35

Closed Vishwas1 closed 2 years ago

Vishwas1 commented 2 years ago

Requirement

Tasks

arnabghose997 commented 2 years ago

Scaffolding a new blockchain

Starport Installation Guide: https://docs.starport.com/guide/install.html

To scaffold the hid-node, run the following:

$ starport scaffold chain hid-node

To scaffold the hid-node without any module, run the following:

$ starport scaffold chain hid-node --no-module
arnabghose997 commented 2 years ago

Building the DID module

PR Reference: hypersign-protocol/hid-node#2

$ starport scaffold module did

modify app/app.go
create proto/did/genesis.proto
create proto/did/params.proto
create proto/did/query.proto
create proto/did/tx.proto
create testutil/keeper/did.go
create x/did/client/cli/query.go
create x/did/client/cli/query_params.go
create x/did/client/cli/tx.go
create x/did/genesis.go
create x/did/genesis_test.go
create x/did/handler.go
create x/did/keeper/grpc_query.go
create x/did/keeper/grpc_query_params.go
create x/did/keeper/grpc_query_params_test.go
create x/did/keeper/keeper.go
create x/did/keeper/msg_server.go
create x/did/keeper/msg_server_test.go
create x/did/keeper/params.go
create x/did/keeper/params_test.go
create x/did/module.go
create x/did/module_simulation.go
create x/did/simulation/simap.go
create x/did/types/codec.go
create x/did/types/errors.go
create x/did/types/expected_keepers.go
create x/did/types/genesis.go
create x/did/types/genesis_test.go
create x/did/types/keys.go
create x/did/types/params.go
create x/did/types/types.go
$ starport scaffold message createDID did didDocString createdAt --module did

modify proto/did/tx.proto
modify x/did/client/cli/tx.go
create x/did/client/cli/tx_create_did.go
modify x/did/handler.go
create x/did/keeper/msg_server_create_did.go
modify x/did/module_simulation.go
create x/did/simulation/create_did.go
modify x/did/types/codec.go
create x/did/types/message_create_did.go
create x/did/types/message_create_did_test.go

🎉 Created a message `createDID`.
syntax = "proto3";
package hypersignprotocol.hidnode.did;

// this line is used by starport scaffolding # proto/tx/import

option go_package = "github.com/hypersign-protocol/hid-node/x/did/types";

// Msg defines the Msg service.
service Msg {
      rpc CreateDID(MsgCreateDID) returns (MsgCreateDIDResponse);
// this line is used by starport scaffolding # proto/tx/rpc
}

message MsgCreateDID {
  string creator = 1;
  string did = 2;
  string didDocString = 3;
  string createdAt = 4;
}

message MsgCreateDIDResponse {
  uint64 id = 1;
}

// this line is used by starport scaffolding # proto/tx/message
package keeper

import (
    "context"

    sdk "github.com/cosmos/cosmos-sdk/types"
    "github.com/hypersign-protocol/hid-node/x/did/types"
)

func (k msgServer) CreateDID(goCtx context.Context, msg *types.MsgCreateDID) (*types.MsgCreateDIDResponse, error) {
    ctx := sdk.UnwrapSDKContext(goCtx)

    var didSpec = types.DidSpec{
        Creator:      msg.Creator,
        Did:          msg.Did,
        DidDocString: msg.DidDocString,
        CreatedAt:    msg.CreatedAt,
    }
    // Add a DID to the store and get back the ID
    id := k.AppendDID(ctx, didSpec)
    // Return the Id of the DID
    return &types.MsgCreateDIDResponse{Id: id}, nil
}
syntax = "proto3";
package hypersignprotocol.hidnode.did;
option go_package = "github.com/hypersign-protocol/hid-node/x/did/types";

message DidSpec {
  string creator = 1;
  uint64 id = 2;
  string did = 3;
  string didDocString = 4; 
  string createdAt = 5;
}
const (
    DidKey      = "Did-value-"
    DidCountKey = "Did-count-"
)
package keeper

import (
    "encoding/binary"

    "github.com/cosmos/cosmos-sdk/store/prefix"
    sdk "github.com/cosmos/cosmos-sdk/types"
    "github.com/hypersign-protocol/hid-node/utils"
    "github.com/hypersign-protocol/hid-node/x/did/types"
)

func (k Keeper) GetDidCount(ctx sdk.Context) uint64 {
    // Get the store using storeKey (which is "blog") and PostCountKey (which is "Post-count-")
    store := prefix.NewStore(ctx.KVStore(k.storeKey), []byte(types.DidCountKey))
    // Convert the PostCountKey to bytes
    byteKey := []byte(types.DidCountKey)
    // Get the value of the count
    bz := store.Get(byteKey)
    // Return zero if the count value is not found (for example, it's the first post)
    if bz == nil {
        return 0
    }
    // Convert the count into a uint64
    return binary.BigEndian.Uint64(bz)
}

func (k Keeper) SetDidCount(ctx sdk.Context, count uint64) {
    // Get the store using storeKey (which is "blog") and PostCountKey (which is "Post-count-")
    store := prefix.NewStore(ctx.KVStore(k.storeKey), []byte(types.DidCountKey))
    // Convert the PostCountKey to bytes
    byteKey := []byte(types.DidCountKey)
    // Convert count from uint64 to string and get bytes
    bz := make([]byte, 8)
    binary.BigEndian.PutUint64(bz, count)
    // Set the value of Post-count- to count
    store.Set(byteKey, bz)
}

func (k Keeper) AppendDID(ctx sdk.Context, didSpec types.DidSpec) uint64 {
    // Get the current number of posts in the store
    count := k.GetDidCount(ctx)
    // Assign an ID to the post based on the number of posts in the store
    didSpec.Id = count
    // Get the store
    store := prefix.NewStore(ctx.KVStore(k.storeKey), []byte(types.DidKey))
    // Convert the post ID into bytes
    byteKey := make([]byte, 8)
    binary.BigEndian.PutUint64(byteKey, didSpec.Id)
    // Marshal the post into bytes
    appendedValue := k.cdc.MustMarshal(&didSpec)
    // Insert the post bytes using post ID as a key

    store.Set(utils.UnsafeStrToBytes(didSpec.Did), appendedValue)
    // Update the post count
    k.SetDidCount(ctx, count+1)
    return count
}

To build a Query service:

$ starport scaffold query dids --response did,didDocString,createdAt
syntax = "proto3";
package hypersignprotocol.hidnode.did;

import "gogoproto/gogo.proto";
import "google/api/annotations.proto";
import "cosmos/base/query/v1beta1/pagination.proto";
import "did/params.proto";
import "did/didSpec.proto";
// this line is used by starport scaffolding # 1

option go_package = "github.com/hypersign-protocol/hid-node/x/did/types";

// Query defines the gRPC querier service.
service Query {
  // Parameters queries the parameters of the module.
  rpc Params(QueryParamsRequest) returns (QueryParamsResponse) {
    option (google.api.http).get = "/hypersignprotocol/hidnode/did/params";
  }
  // Queries a list of Dids items.
    rpc Dids(QueryDidsRequest) returns (QueryDidsResponse) {
        option (google.api.http).get = "/hypersign-protocol/hidnode/did/{did}";
    }

// this line is used by starport scaffolding # 2
}

// QueryParamsRequest is request type for the Query/Params RPC method.
message QueryParamsRequest {}

// QueryParamsResponse is response type for the Query/Params RPC method.
message QueryParamsResponse {
  // params holds all the parameters of this module.
  Params params = 1 [(gogoproto.nullable) = false];
}

message QueryDidsRequest {
  string did = 1;
}

message QueryDidsResponse {
  string didDoc = 1;
}

// this line is used by starport scaffolding # 3
package keeper

import (
    "context"

    "github.com/cosmos/cosmos-sdk/store/prefix"
    sdk "github.com/cosmos/cosmos-sdk/types"
    "github.com/hypersign-protocol/hid-node/utils"
    "github.com/hypersign-protocol/hid-node/x/did/types"
    "google.golang.org/grpc/codes"
    "google.golang.org/grpc/status"
)

func (k Keeper) Dids(goCtx context.Context, req *types.QueryDidsRequest) (*types.QueryDidsResponse, error) {
    if req == nil {
        return nil, status.Error(codes.InvalidArgument, "invalid request")
    }

    // Get context with the information about the environment
    ctx := sdk.UnwrapSDKContext(goCtx)
    // Get the key-value module store using the store key (in our case store key is "chain")
    store := ctx.KVStore(k.storeKey)
    // Get the part of the store that keeps posts (using post key, which is "Post-value-")
    didStore := prefix.NewStore(store, []byte(types.DidKey))
    bz := didStore.Get(utils.UnsafeStrToBytes(req.Did))

    // Return a struct containing a list of posts and pagination info
    return &types.QueryDidsResponse{DidDoc: utils.UnsafeBytesToStr(bz)}, nil
}
func (AppModuleBasic) RegisterGRPCGatewayRoutes(clientCtx client.Context, mux *runtime.ServeMux) {
    types.RegisterQueryHandlerClient(context.Background(), mux, types.NewQueryClient(clientCtx))
}
arnabghose997 commented 2 years ago

The prominent libraries used in Golang for cryptography are:

import (
    "crypto/ed25519"
    "encoding/base64"
)

Following are the lengths for key sizes:

//File ed25519.go

const (
    // PublicKeySize is the size, in bytes, of public keys as used in this package.
    PublicKeySize = 32
    // PrivateKeySize is the size, in bytes, of private keys as used in this package.
    PrivateKeySize = 64
    // SignatureSize is the size, in bytes, of signatures generated and verified by this package.
    SignatureSize = 64
    // SeedSize is the size, in bytes, of private key seeds. These are the private key representations used by RFC 8032.
    SeedSize = 32
)
arnabghose997 commented 2 years ago

Following are the Sign and Verify implementations of ed25519 Golang library:

Sign

// Sign signs the message with privateKey and returns a signature. It will
// panic if len(privateKey) is not PrivateKeySize.
func Sign(privateKey PrivateKey, message []byte) []byte {
    // Outline the function body so that the returned signature can be
    // stack-allocated.
    signature := make([]byte, SignatureSize)
    sign(signature, privateKey, message)
    return signature
}

func sign(signature, privateKey, message []byte) {
    if l := len(privateKey); l != PrivateKeySize {
        panic("ed25519: bad private key length: " + strconv.Itoa(l))
    }
    seed, publicKey := privateKey[:SeedSize], privateKey[SeedSize:]

    h := sha512.Sum512(seed)
    s := edwards25519.NewScalar().SetBytesWithClamping(h[:32])
    prefix := h[32:]

    mh := sha512.New()
    mh.Write(prefix)
    mh.Write(message)
    messageDigest := make([]byte, 0, sha512.Size)
    messageDigest = mh.Sum(messageDigest)
    r := edwards25519.NewScalar().SetUniformBytes(messageDigest)

    R := (&edwards25519.Point{}).ScalarBaseMult(r)

    kh := sha512.New()
    kh.Write(R.Bytes())
    kh.Write(publicKey)
    kh.Write(message)
    hramDigest := make([]byte, 0, sha512.Size)
    hramDigest = kh.Sum(hramDigest)
    k := edwards25519.NewScalar().SetUniformBytes(hramDigest)

    S := edwards25519.NewScalar().MultiplyAdd(k, s, r)

    copy(signature[:32], R.Bytes())
    copy(signature[32:], S.Bytes())
}

Verify

// Verify reports whether sig is a valid signature of message by publicKey. It
// will panic if len(publicKey) is not PublicKeySize.
func Verify(publicKey PublicKey, message, sig []byte) bool {
    if l := len(publicKey); l != PublicKeySize {
        panic("ed25519: bad public key length: " + strconv.Itoa(l))
    }

    if len(sig) != SignatureSize || sig[63]&224 != 0 {
        return false
    }

    A, err := (&edwards25519.Point{}).SetBytes(publicKey)
    if err != nil {
        return false
    }

    kh := sha512.New()
    kh.Write(sig[:32])
    kh.Write(publicKey)
    kh.Write(message)
    hramDigest := make([]byte, 0, sha512.Size)
    hramDigest = kh.Sum(hramDigest)
    k := edwards25519.NewScalar().SetUniformBytes(hramDigest)

    S, err := edwards25519.NewScalar().SetCanonicalBytes(sig[32:])
    if err != nil {
        return false
    }

    // [S]B = R + [k]A --> [k](-A) + [S]B = R
    minusA := (&edwards25519.Point{}).Negate(A)
    R := (&edwards25519.Point{}).VarTimeDoubleScalarBaseMult(k, minusA, S)

    return bytes.Equal(sig[:32], R.Bytes())
}
Vishwas1 commented 2 years ago

Following are the Sign and Verify implementations of ed25519 Golang library:

Sign

// Sign signs the message with privateKey and returns a signature. It will
// panic if len(privateKey) is not PrivateKeySize.
func Sign(privateKey PrivateKey, message []byte) []byte {
    // Outline the function body so that the returned signature can be
    // stack-allocated.
    signature := make([]byte, SignatureSize)
    sign(signature, privateKey, message)
    return signature
}

func sign(signature, privateKey, message []byte) {
    if l := len(privateKey); l != PrivateKeySize {
        panic("ed25519: bad private key length: " + strconv.Itoa(l))
    }
    seed, publicKey := privateKey[:SeedSize], privateKey[SeedSize:]

    h := sha512.Sum512(seed)
    s := edwards25519.NewScalar().SetBytesWithClamping(h[:32])
    prefix := h[32:]

    mh := sha512.New()
    mh.Write(prefix)
    mh.Write(message)
    messageDigest := make([]byte, 0, sha512.Size)
    messageDigest = mh.Sum(messageDigest)
    r := edwards25519.NewScalar().SetUniformBytes(messageDigest)

    R := (&edwards25519.Point{}).ScalarBaseMult(r)

    kh := sha512.New()
    kh.Write(R.Bytes())
    kh.Write(publicKey)
    kh.Write(message)
    hramDigest := make([]byte, 0, sha512.Size)
    hramDigest = kh.Sum(hramDigest)
    k := edwards25519.NewScalar().SetUniformBytes(hramDigest)

    S := edwards25519.NewScalar().MultiplyAdd(k, s, r)

    copy(signature[:32], R.Bytes())
    copy(signature[32:], S.Bytes())
}

Verify

// Verify reports whether sig is a valid signature of message by publicKey. It
// will panic if len(publicKey) is not PublicKeySize.
func Verify(publicKey PublicKey, message, sig []byte) bool {
    if l := len(publicKey); l != PublicKeySize {
        panic("ed25519: bad public key length: " + strconv.Itoa(l))
    }

    if len(sig) != SignatureSize || sig[63]&224 != 0 {
        return false
    }

    A, err := (&edwards25519.Point{}).SetBytes(publicKey)
    if err != nil {
        return false
    }

    kh := sha512.New()
    kh.Write(sig[:32])
    kh.Write(publicKey)
    kh.Write(message)
    hramDigest := make([]byte, 0, sha512.Size)
    hramDigest = kh.Sum(hramDigest)
    k := edwards25519.NewScalar().SetUniformBytes(hramDigest)

    S, err := edwards25519.NewScalar().SetCanonicalBytes(sig[32:])
    if err != nil {
        return false
    }

    // [S]B = R + [k]A --> [k](-A) + [S]B = R
    minusA := (&edwards25519.Point{}).Negate(A)
    R := (&edwards25519.Point{}).VarTimeDoubleScalarBaseMult(k, minusA, S)

    return bytes.Equal(sig[:32], R.Bytes())
}

@arnabghose997 I was wondering if you have executed them independently ? I mean imagine I have a message and I want to use those above codes to sign and verify the signature, can I do that ?

arnabghose997 commented 2 years ago

@Vishwas1 Yes that's possible, but I just went through their implementation, instead of running them separately . While going through the cheqd-node code, I saw the usage of of these functions as ed25519.Sign() and ed25519.Verify().

arnabghose997 commented 2 years ago

Info for Coin Metadata : https://docs.cosmos.network/master/architecture/adr-024-coin-metadata.html

Cosmos Chain Registry (Metadata about all Cosmos Chains): https://github.com/cosmos/chain-registry/

Genesis File for Reference: https://github.com/persistenceOne/networks/blob/master/test-core-1/final_genesis.json

This forum post will serve as a good reference while going for testnet: https://forum.cosmos.network/t/using-an-aws-ec2-as-a-cosmos-node/845