mirror of
https://github.com/onsonr/sonr.git
synced 2025-03-10 21:09:11 +00:00
- **refactor: remove unused auth components** - **refactor: improve devbox configuration and deployment process** - **refactor: improve devnet and testnet setup** - **fix: update templ version to v0.2.778** - **refactor: rename pkl/net.matrix to pkl/matrix.net** - **refactor: migrate webapp components to nebula** - **refactor: protobuf types** - **chore: update dependencies for improved security and stability** - **feat: implement landing page and vault gateway servers** - **refactor: Migrate data models to new module structure and update related files** - **feature/1121-implement-ucan-validation** - **refactor: Replace hardcoded constants with model types in attns.go** - **feature/1121-implement-ucan-validation** - **chore: add origin Host struct and update main function to handle multiple hosts** - **build: remove unused static files from dwn module** - **build: remove unused static files from dwn module** - **refactor: Move DWN models to common package** - **refactor: move models to pkg/common** - **refactor: move vault web app assets to embed module** - **refactor: update session middleware import path** - **chore: configure port labels and auto-forwarding behavior** - **feat: enhance devcontainer configuration** - **feat: Add UCAN middleware for Echo with flexible token validation** - **feat: add JWT middleware for UCAN authentication** - **refactor: update package URI and versioning in PklProject files** - **fix: correct sonr.pkl import path** - **refactor: move JWT related code to auth package** - **feat: introduce vault configuration retrieval and management** - **refactor: Move vault components to gateway module and update file paths** - **refactor: remove Dexie and SQLite database implementations** - **feat: enhance frontend with PWA features and WASM integration** - **feat: add Devbox features and streamline Dockerfile** - **chore: update dependencies to include TigerBeetle** - **chore(deps): update go version to 1.23** - **feat: enhance devnet setup with PATH environment variable and updated PWA manifest** - **fix: upgrade tigerbeetle-go dependency and remove indirect dependency** - **feat: add PostgreSQL support to devnet and testnet deployments** - **refactor: rename keyshare cookie to token cookie** - **feat: upgrade Go version to 1.23.3 and update dependencies** - **refactor: update devnet and testnet configurations** - **feat: add IPFS configuration for devnet** - **I'll help you update the ipfs.config.pkl to include all the peers from the shell script. Here's the updated configuration:** - **refactor: move mpc package to crypto directory** - **feat: add BIP32 support for various cryptocurrencies** - **feat: enhance ATN.pkl with additional capabilities** - **refactor: simplify smart account and vault attenuation creation** - **feat: add new capabilities to the Attenuation type** - **refactor: Rename MPC files for clarity and consistency** - **feat: add DIDKey support for cryptographic operations** - **feat: add devnet and testnet deployment configurations** - **fix: correct key derivation in bip32 package** - **refactor: rename crypto/bip32 package to crypto/accaddr** - **fix: remove duplicate indirect dependency** - **refactor: move vault package to root directory** - **refactor: update routes for gateway and vault** - **refactor: remove obsolete web configuration file** - **refactor: remove unused TigerBeetle imports and update host configuration** - **refactor: adjust styles directory path** - **feat: add broadcastTx and simulateTx functions to gateway** - **feat: add PinVault handler**
447 lines
16 KiB
Go
Executable File
447 lines
16 KiB
Go
Executable File
//
|
|
// Copyright Coinbase, Inc. All Rights Reserved.
|
|
//
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
//
|
|
|
|
package bls_sig
|
|
|
|
import (
|
|
"fmt"
|
|
)
|
|
|
|
const (
|
|
// Domain separation tag for basic signatures
|
|
// according to section 4.2.1 in
|
|
// https://tools.ietf.org/html/draft-irtf-cfrg-bls-signature-03
|
|
blsSignatureBasicDst = "BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_NUL_"
|
|
// Domain separation tag for basic signatures
|
|
// according to section 4.2.2 in
|
|
// https://tools.ietf.org/html/draft-irtf-cfrg-bls-signature-03
|
|
blsSignatureAugDst = "BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_AUG_"
|
|
// Domain separation tag for proof of possession signatures
|
|
// according to section 4.2.3 in
|
|
// https://tools.ietf.org/html/draft-irtf-cfrg-bls-signature-03
|
|
blsSignaturePopDst = "BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_POP_"
|
|
// Domain separation tag for proof of possession proofs
|
|
// according to section 4.2.3 in
|
|
// https://tools.ietf.org/html/draft-irtf-cfrg-bls-signature-03
|
|
blsPopProofDst = "BLS_POP_BLS12381G2_XMD:SHA-256_SSWU_RO_POP_"
|
|
)
|
|
|
|
type BlsScheme interface {
|
|
Keygen() (*PublicKey, *SecretKey, error)
|
|
KeygenWithSeed(ikm []byte) (*PublicKey, *SecretKey, error)
|
|
Sign(sk *SecretKey, msg []byte) (*Signature, error)
|
|
Verify(pk *PublicKey, msg []byte, sig *Signature) bool
|
|
AggregateVerify(pks []*PublicKey, msgs [][]byte, sigs []*Signature) bool
|
|
}
|
|
|
|
// generateKeys creates 32 bytes of random data to be fed to
|
|
// generateKeysWithSeed
|
|
func generateKeys() (*PublicKey, *SecretKey, error) {
|
|
ikm, err := generateRandBytes(32)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
return generateKeysWithSeed(ikm)
|
|
}
|
|
|
|
// generateKeysWithSeed generates a BLS key pair given input key material (ikm)
|
|
func generateKeysWithSeed(ikm []byte) (*PublicKey, *SecretKey, error) {
|
|
sk, err := new(SecretKey).Generate(ikm)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
pk, err := sk.GetPublicKey()
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
return pk, sk, nil
|
|
}
|
|
|
|
// thresholdGenerateKeys will generate random secret key shares and the corresponding public key
|
|
func thresholdGenerateKeys(threshold, total uint) (*PublicKey, []*SecretKeyShare, error) {
|
|
pk, sk, err := generateKeys()
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
shares, err := thresholdizeSecretKey(sk, threshold, total)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
return pk, shares, nil
|
|
}
|
|
|
|
// thresholdGenerateKeysWithSeed will generate random secret key shares and the corresponding public key
|
|
// using the corresponding seed `ikm`
|
|
func thresholdGenerateKeysWithSeed(ikm []byte, threshold, total uint) (*PublicKey, []*SecretKeyShare, error) {
|
|
pk, sk, err := generateKeysWithSeed(ikm)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
shares, err := thresholdizeSecretKey(sk, threshold, total)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
return pk, shares, nil
|
|
}
|
|
|
|
// SigBasic is minimal-pubkey-size scheme that doesn't support FastAggregateVerificiation.
|
|
// see: https://tools.ietf.org/html/draft-irtf-cfrg-bls-signature-03#section-4.2.1
|
|
type SigBasic struct {
|
|
dst string
|
|
}
|
|
|
|
// Creates a new BLS basic signature scheme with the standard domain separation tag used for signatures.
|
|
func NewSigBasic() *SigBasic {
|
|
return &SigBasic{dst: blsSignatureBasicDst}
|
|
}
|
|
|
|
// Creates a new BLS basic signature scheme with a custom domain separation tag used for signatures.
|
|
func NewSigBasicWithDst(signDst string) *SigBasic {
|
|
return &SigBasic{dst: signDst}
|
|
}
|
|
|
|
// Creates a new BLS key pair
|
|
func (b SigBasic) Keygen() (*PublicKey, *SecretKey, error) {
|
|
return generateKeys()
|
|
}
|
|
|
|
// Creates a new BLS key pair
|
|
// Input key material (ikm) MUST be at least 32 bytes long,
|
|
// but it MAY be longer.
|
|
func (b SigBasic) KeygenWithSeed(ikm []byte) (*PublicKey, *SecretKey, error) {
|
|
return generateKeysWithSeed(ikm)
|
|
}
|
|
|
|
// ThresholdKeyGen generates a public key and `total` secret key shares such that
|
|
// `threshold` of them can be combined in signatures
|
|
func (b SigBasic) ThresholdKeygen(threshold, total uint) (*PublicKey, []*SecretKeyShare, error) {
|
|
return thresholdGenerateKeys(threshold, total)
|
|
}
|
|
|
|
// ThresholdKeyGen generates a public key and `total` secret key shares such that
|
|
// `threshold` of them can be combined in signatures
|
|
func (b SigBasic) ThresholdKeygenWithSeed(ikm []byte, threshold, total uint) (*PublicKey, []*SecretKeyShare, error) {
|
|
return thresholdGenerateKeysWithSeed(ikm, threshold, total)
|
|
}
|
|
|
|
// Computes a signature in G2 from sk, a secret key, and a message
|
|
func (b SigBasic) Sign(sk *SecretKey, msg []byte) (*Signature, error) {
|
|
return sk.createSignature(msg, b.dst)
|
|
}
|
|
|
|
// Compute a partial signature in G2 that can be combined with other partial signature
|
|
func (b SigBasic) PartialSign(sks *SecretKeyShare, msg []byte) (*PartialSignature, error) {
|
|
return sks.partialSign(msg, b.dst)
|
|
}
|
|
|
|
// CombineSignatures takes partial signatures to yield a completed signature
|
|
func (b SigBasic) CombineSignatures(sigs ...*PartialSignature) (*Signature, error) {
|
|
return combineSigs(sigs)
|
|
}
|
|
|
|
// Checks that a signature is valid for the message under the public key pk
|
|
func (b SigBasic) Verify(pk *PublicKey, msg []byte, sig *Signature) (bool, error) {
|
|
return pk.verifySignature(msg, sig, b.dst)
|
|
}
|
|
|
|
// The AggregateVerify algorithm checks an aggregated signature over
|
|
// several (PK, message, signature) pairs.
|
|
// Each message must be different or this will return false.
|
|
// See section 3.1.1 from
|
|
// https://tools.ietf.org/html/draft-irtf-cfrg-bls-signature-03
|
|
func (b SigBasic) AggregateVerify(pks []*PublicKey, msgs [][]byte, sigs []*Signature) (bool, error) {
|
|
if !allRowsUnique(msgs) {
|
|
return false, fmt.Errorf("all messages must be distinct")
|
|
}
|
|
asig, err := aggregateSignatures(sigs...)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
return asig.aggregateVerify(pks, msgs, b.dst)
|
|
}
|
|
|
|
// SigAug is minimal-pubkey-size scheme that doesn't support FastAggregateVerificiation.
|
|
// see: https://tools.ietf.org/html/draft-irtf-cfrg-bls-signature-03#section-4.2.2
|
|
type SigAug struct {
|
|
dst string
|
|
}
|
|
|
|
// Creates a new BLS message augmentation signature scheme with the standard domain separation tag used for signatures.
|
|
func NewSigAug() *SigAug {
|
|
return &SigAug{dst: blsSignatureAugDst}
|
|
}
|
|
|
|
// Creates a new BLS message augmentation signature scheme with a custom domain separation tag used for signatures.
|
|
func NewSigAugWithDst(signDst string) *SigAug {
|
|
return &SigAug{dst: signDst}
|
|
}
|
|
|
|
// Creates a new BLS key pair
|
|
func (b SigAug) Keygen() (*PublicKey, *SecretKey, error) {
|
|
return generateKeys()
|
|
}
|
|
|
|
// Creates a new BLS secret key
|
|
// Input key material (ikm) MUST be at least 32 bytes long,
|
|
// but it MAY be longer.
|
|
func (b SigAug) KeygenWithSeed(ikm []byte) (*PublicKey, *SecretKey, error) {
|
|
return generateKeysWithSeed(ikm)
|
|
}
|
|
|
|
// ThresholdKeyGen generates a public key and `total` secret key shares such that
|
|
// `threshold` of them can be combined in signatures
|
|
func (b SigAug) ThresholdKeygen(threshold, total uint) (*PublicKey, []*SecretKeyShare, error) {
|
|
return thresholdGenerateKeys(threshold, total)
|
|
}
|
|
|
|
// ThresholdKeyGen generates a public key and `total` secret key shares such that
|
|
// `threshold` of them can be combined in signatures
|
|
func (b SigAug) ThresholdKeygenWithSeed(ikm []byte, threshold, total uint) (*PublicKey, []*SecretKeyShare, error) {
|
|
return thresholdGenerateKeysWithSeed(ikm, threshold, total)
|
|
}
|
|
|
|
// Computes a signature in G1 from sk, a secret key, and a message
|
|
// See section 3.2.1 from
|
|
// https://tools.ietf.org/html/draft-irtf-cfrg-bls-signature-03
|
|
func (b SigAug) Sign(sk *SecretKey, msg []byte) (*Signature, error) {
|
|
if len(msg) == 0 {
|
|
return nil, fmt.Errorf("message cannot be empty or nil")
|
|
}
|
|
|
|
pk, err := sk.GetPublicKey()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
bytes, err := pk.MarshalBinary()
|
|
if err != nil {
|
|
return nil, fmt.Errorf("MarshalBinary failed")
|
|
}
|
|
bytes = append(bytes, msg...)
|
|
return sk.createSignature(bytes, b.dst)
|
|
}
|
|
|
|
// Compute a partial signature in G2 that can be combined with other partial signature
|
|
func (b SigAug) PartialSign(sks *SecretKeyShare, pk *PublicKey, msg []byte) (*PartialSignature, error) {
|
|
if len(msg) == 0 {
|
|
return nil, fmt.Errorf("message cannot be empty or nil")
|
|
}
|
|
|
|
bytes, err := pk.MarshalBinary()
|
|
if err != nil {
|
|
return nil, fmt.Errorf("MarshalBinary failed")
|
|
}
|
|
bytes = append(bytes, msg...)
|
|
return sks.partialSign(bytes, b.dst)
|
|
}
|
|
|
|
// CombineSignatures takes partial signatures to yield a completed signature
|
|
func (b SigAug) CombineSignatures(sigs ...*PartialSignature) (*Signature, error) {
|
|
return combineSigs(sigs)
|
|
}
|
|
|
|
// Checks that a signature is valid for the message under the public key pk
|
|
// See section 3.2.2 from
|
|
// https://tools.ietf.org/html/draft-irtf-cfrg-bls-signature-03
|
|
func (b SigAug) Verify(pk *PublicKey, msg []byte, sig *Signature) (bool, error) {
|
|
bytes, err := pk.MarshalBinary()
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
bytes = append(bytes, msg...)
|
|
return pk.verifySignature(bytes, sig, b.dst)
|
|
}
|
|
|
|
// The AggregateVerify algorithm checks an aggregated signature over
|
|
// several (PK, message, signature) pairs.
|
|
// See section 3.2.3 from
|
|
// https://tools.ietf.org/html/draft-irtf-cfrg-bls-signature-03
|
|
func (b SigAug) AggregateVerify(pks []*PublicKey, msgs [][]byte, sigs []*Signature) (bool, error) {
|
|
if len(pks) != len(msgs) {
|
|
return false, fmt.Errorf("the number of public keys does not match the number of messages: %v != %v", len(pks), len(msgs))
|
|
}
|
|
data := make([][]byte, len(msgs))
|
|
for i, msg := range msgs {
|
|
bytes, err := pks[i].MarshalBinary()
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
data[i] = append(bytes, msg...)
|
|
}
|
|
asig, err := aggregateSignatures(sigs...)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
return asig.aggregateVerify(pks, data, b.dst)
|
|
}
|
|
|
|
// SigEth2 supports signatures on Eth2.
|
|
// Internally is an alias for SigPop
|
|
type SigEth2 = SigPop
|
|
|
|
// NewSigEth2 Creates a new BLS ETH2 signature scheme with the standard domain separation tag used for signatures.
|
|
func NewSigEth2() *SigEth2 {
|
|
return NewSigPop()
|
|
}
|
|
|
|
// SigPop is minimal-pubkey-size scheme that supports FastAggregateVerification
|
|
// and requires using proofs of possession to mitigate rogue-key attacks
|
|
// see: https://tools.ietf.org/html/draft-irtf-cfrg-bls-signature-03#section-4.2.3
|
|
type SigPop struct {
|
|
sigDst string
|
|
popDst string
|
|
}
|
|
|
|
// Creates a new BLS proof of possession signature scheme with the standard domain separation tag used for signatures.
|
|
func NewSigPop() *SigPop {
|
|
return &SigPop{sigDst: blsSignaturePopDst, popDst: blsPopProofDst}
|
|
}
|
|
|
|
// Creates a new BLS message proof of possession signature scheme with a custom domain separation tag used for signatures.
|
|
func NewSigPopWithDst(signDst, popDst string) (*SigPop, error) {
|
|
if signDst == popDst {
|
|
return nil, fmt.Errorf("domain separation tags cannot be equal")
|
|
}
|
|
return &SigPop{sigDst: signDst, popDst: popDst}, nil
|
|
}
|
|
|
|
// Creates a new BLS key pair
|
|
func (b SigPop) Keygen() (*PublicKey, *SecretKey, error) {
|
|
return generateKeys()
|
|
}
|
|
|
|
// Creates a new BLS secret key
|
|
// Input key material (ikm) MUST be at least 32 bytes long,
|
|
// but it MAY be longer.
|
|
func (b SigPop) KeygenWithSeed(ikm []byte) (*PublicKey, *SecretKey, error) {
|
|
return generateKeysWithSeed(ikm)
|
|
}
|
|
|
|
// ThresholdKeyGen generates a public key and `total` secret key shares such that
|
|
// `threshold` of them can be combined in signatures
|
|
func (b SigPop) ThresholdKeygen(threshold, total uint) (*PublicKey, []*SecretKeyShare, error) {
|
|
return thresholdGenerateKeys(threshold, total)
|
|
}
|
|
|
|
// ThresholdKeyGen generates a public key and `total` secret key shares such that
|
|
// `threshold` of them can be combined in signatures
|
|
func (b SigPop) ThresholdKeygenWithSeed(ikm []byte, threshold, total uint) (*PublicKey, []*SecretKeyShare, error) {
|
|
return thresholdGenerateKeysWithSeed(ikm, threshold, total)
|
|
}
|
|
|
|
// Computes a signature in G2 from sk, a secret key, and a message
|
|
// See section 2.6 from
|
|
// https://tools.ietf.org/html/draft-irtf-cfrg-bls-signature-03
|
|
func (b SigPop) Sign(sk *SecretKey, msg []byte) (*Signature, error) {
|
|
return sk.createSignature(msg, b.sigDst)
|
|
}
|
|
|
|
// Compute a partial signature in G2 that can be combined with other partial signature
|
|
func (b SigPop) PartialSign(sks *SecretKeyShare, msg []byte) (*PartialSignature, error) {
|
|
return sks.partialSign(msg, b.sigDst)
|
|
}
|
|
|
|
// CombineSignatures takes partial signatures to yield a completed signature
|
|
func (b SigPop) CombineSignatures(sigs ...*PartialSignature) (*Signature, error) {
|
|
return combineSigs(sigs)
|
|
}
|
|
|
|
// Checks that a signature is valid for the message under the public key pk
|
|
// See section 2.7 from
|
|
// https://tools.ietf.org/html/draft-irtf-cfrg-bls-signature-03
|
|
func (b SigPop) Verify(pk *PublicKey, msg []byte, sig *Signature) (bool, error) {
|
|
return pk.verifySignature(msg, sig, b.sigDst)
|
|
}
|
|
|
|
// The aggregateVerify algorithm checks an aggregated signature over
|
|
// several (PK, message, signature) pairs.
|
|
// Each message must be different or this will return false.
|
|
// See section 3.1.1 from
|
|
// https://tools.ietf.org/html/draft-irtf-cfrg-bls-signature-03
|
|
func (b SigPop) AggregateVerify(pks []*PublicKey, msgs [][]byte, sigs []*Signature) (bool, error) {
|
|
if !allRowsUnique(msgs) {
|
|
return false, fmt.Errorf("all messages must be distinct")
|
|
}
|
|
asig, err := aggregateSignatures(sigs...)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
return asig.aggregateVerify(pks, msgs, b.sigDst)
|
|
}
|
|
|
|
// Combine many signatures together to form a Multisignature.
|
|
// Multisignatures can be created when multiple signers jointly
|
|
// generate signatures over the same message.
|
|
func (b SigPop) AggregateSignatures(sigs ...*Signature) (*MultiSignature, error) {
|
|
g1, err := aggregateSignatures(sigs...)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &MultiSignature{value: g1.Value}, nil
|
|
}
|
|
|
|
// Combine many public keys together to form a Multipublickey.
|
|
// Multipublickeys are used to verify multisignatures.
|
|
func (b SigPop) AggregatePublicKeys(pks ...*PublicKey) (*MultiPublicKey, error) {
|
|
g2, err := aggregatePublicKeys(pks...)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &MultiPublicKey{value: g2.value}, nil
|
|
}
|
|
|
|
// Checks that a multisignature is valid for the message under the multi public key
|
|
// Similar to FastAggregateVerify except the keys and signatures have already been
|
|
// combined. See section 3.3.4 from
|
|
// https://tools.ietf.org/html/draft-irtf-cfrg-bls-signature-03
|
|
func (b SigPop) VerifyMultiSignature(pk *MultiPublicKey, msg []byte, sig *MultiSignature) (bool, error) {
|
|
s := &Signature{Value: sig.value}
|
|
p := &PublicKey{value: pk.value}
|
|
return p.verifySignature(msg, s, b.sigDst)
|
|
}
|
|
|
|
// FastAggregateVerify verifies an aggregated signature against the specified message and set of public keys.
|
|
// See section 3.3.4 from
|
|
// https://tools.ietf.org/html/draft-irtf-cfrg-bls-signature-03
|
|
func (b SigPop) FastAggregateVerify(pks []*PublicKey, msg []byte, asig *Signature) (bool, error) {
|
|
apk, err := aggregatePublicKeys(pks...)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
return apk.verifySignature(msg, asig, b.sigDst)
|
|
}
|
|
|
|
// FastAggregateVerifyConstituent aggregates all constituent signatures and the verifies
|
|
// them against the specified message and public keys
|
|
// See section 3.3.4 from
|
|
// https://tools.ietf.org/html/draft-irtf-cfrg-bls-signature-03
|
|
func (b SigPop) FastAggregateVerifyConstituent(pks []*PublicKey, msg []byte, sigs []*Signature) (bool, error) {
|
|
// Aggregate the constituent signatures
|
|
asig, err := aggregateSignatures(sigs...)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
// And verify
|
|
return b.FastAggregateVerify(pks, msg, asig)
|
|
}
|
|
|
|
// Create a proof of possession for the corresponding public key.
|
|
// A proof of possession must be created for each public key to be used
|
|
// in FastAggregateVerify or a Multipublickey to avoid rogue key attacks.
|
|
// See section 3.3.2 from
|
|
// https://tools.ietf.org/html/draft-irtf-cfrg-bls-signature-03
|
|
func (b SigPop) PopProve(sk *SecretKey) (*ProofOfPossession, error) {
|
|
return sk.createProofOfPossession(b.popDst)
|
|
}
|
|
|
|
// verify a proof of possession for the corresponding public key is valid.
|
|
// A proof of possession must be created for each public key to be used
|
|
// in FastAggregateVerify or a Multipublickey to avoid rogue key attacks.
|
|
// See section 3.3.3 from
|
|
// https://tools.ietf.org/html/draft-irtf-cfrg-bls-signature-03
|
|
func (b SigPop) PopVerify(pk *PublicKey, pop2 *ProofOfPossession) (bool, error) {
|
|
return pop2.verify(pk, b.popDst)
|
|
}
|