crypto

package
v0.1.14 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 11, 2024 License: Apache-2.0 Imports: 22 Imported by: 35

README

CGO Binding Guide

Software Requirement

  • CMAKE (Version at least 3.10.2)
    • Install on MacOS:
      brew install cmake
    
    • Install on Linux:
      wget http://www.cmake.org/files/v3.11/cmake-3.11.0-Linux-x86_64.tar.gz
      tar -xvf cmake-3.11.0-Linux-x86_64.tar.gz
      cd cmake-3.11.0-Linux-x86_64
      sudo  cp -r bin /usr/
      sudo  cp -r share /usr/
      sudo  cp -r doc /usr/share/
      sudo  cp -r man /usr/share/
    

CGO Development Guide

1. Declare the use of CGO and files binding
 //#include "lib/ecckey.h"
 //#include "lib/ecckey.c"
 import “C”
  • Just use import “C” to start using CGO. It comes with Go. No need to install any other library.
  • “//” is not a regular comment sign in CGO declaration. It starts a directive and will not be ignored by compiler.
  • import “C” should be immediately preceded by //#include XXX or //#cgo.
  • //#include XXX indicates the use of c header files and c source code files
  • //#cgo is used to indicate the use of flags like CFLAGS, CPPFLAGS, CXXFLAGS, FFLAGS and LDFLAGS etc. to tweak the behavior of C, C++ compiler. The //#cgo directive can also include a list of build constraints that limit the os and architecture. It can also indicates the C library, so that you do not have to include the source code files.
//#cgo darwin LDFLAGS: -L${SRCDIR}/lib -lsect283k1_macos
//#cgo linux LDFLAGS: -L${SRCDIR}/lib -lsect283k1_ubuntu

This indicates the library sect283k1_macos will be used in Mac platform,
sect283k1_ubuntu in Linux platform. Both of them are located in directory ${SRCDIR}/lib. -L specifies the location of the library.

package crypto

//#include "lib/ecckey.h"
//#include "lib/ecdsa.h"
//#include "lib/sect283k1.h"
//#cgo darwin LDFLAGS: -L${SRCDIR}/lib -lsect283k1_macos
//#cgo linux LDFLAGS: -L${SRCDIR}/lib -lsect283k1_ubuntu
import "C"
import (
    "bytes"
    "encoding/binary"
    "errors"

    "github.com/iotexproject/iotex-core/pkg/enc"
    "github.com/iotexproject/go-pkgs/crypto"
)
2. Go references C
  • Go calls C functions: Just call C.function_name_in_C(…)
  • Go uses any type in C: C.type_in_C, like C.uint32_t, C.ec_point_aff_twist
  • Pointer pass in CGO is the same as in go
  • Go can access any fields of C struct in the same way in Go struct
    // C header file
    
    typedef struct
    {
        uint32_t d[9];         
        ec283_point_lambda_aff Q;
    }ec283_key_pair;
    
    void keypair_generation(ec283_key_pair *key);
    
    // Go file
    func (c *ec283) NewKeyPair() (keypair.PublicKey, keypair.PrivateKey, error) {
        var kp C.ec283_key_pair
        C.keypair_generation(&kp)
        pubKey := kp.Q
        privKey := kp.d
        ...
    }
    
  • Primitive type conversion: Just cast the type from C type to Go or from Go to C
    // privkey has go type elements, privkeySer has C type elements
    for i := 0; i < privkeySize; i++ {
        privkeySer[i] = (C.uint32_t)(privkey[i])
    }
    
    // sigSer has C type elements, sig has go type elements
    for i, x := range sigSer {
        sig[i] = (uint32)(x)
    }
    
3. Go passes an array to C

Just pass the first element of the slice as a pointer, and cast the pointer to C corresponding
type. The slice in Go is a struct including header and elements, so &slice won’t give you the
first element.

// C file
// d and sig are arrays

uint32_t BLS_sign(uint32_t *d, const uint8_t *msg, uint64_t mlen, uint32_t *sig);

// Go file
// Sign signs a message given a private key

func (b *bls) Sign(privkey []uint32, msg []byte) (bool, []byte, error) {
    var sigSer [sigSize]C.uint32_t
    msgString := string(msg[:])

    if ok := C.BLS_sign((*C.uint32_t)(unsafe.Pointer(&privkey[0])), (*C.uint8_t)(&msg[0]), (C.uint64_t)(len(msgString)), &sigSer[0]); ok == 1 {
        sig, err := b.signatureSerialization(sigSer)
        if err != nil {
            return false, []byte{}, err
        }
        return true, sig, nil
    }
    return false, []byte{}, ErrSignError
}

4. Use struct defined in C
  • Construct a corresponding struct in Go that mimics the same struct in C.
  • (Recommended) Write function to serialize and deserialize the the struct, so the information can be exposed outside independently.
    // C header file and C struct definition
    typedef struct
    {
        uint32_t x[9];     
        uint32_t l[9];     
    }ec283_point_lambda_aff;
    
    // Go file
    
    func (*ec283) publicKeySerialization(pubKey C.ec283_point_lambda_aff) (keypair.PublicKey, error) {
        var xl [18]uint32
        for i := 0; i < 9; i++ {
            xl[i] = (uint32)(pubKey.x[i])
            xl[i+9] = (uint32)(pubKey.l[i])
        }
        buf := new(bytes.Buffer)
        err := binary.Write(buf, enc.MachineEndian, xl)
        if err != nil {
            return keypair.ZeroPublicKey, err
        }
        return keypair.BytesToPublicKey(buf.Bytes())
    }
    
    func (*ec283) publicKeyDeserialization(pubKey keypair.PublicKey) (C.ec283_point_lambda_aff, error) {
        var xl [18]uint32
        var pub C.ec283_point_lambda_aff
        rbuf := bytes.NewReader(pubKey[:])
        err := binary.Read(rbuf, enc.MachineEndian, &xl)
        if err != nil {
            return pub, err
        }
        for i := 0; i < 9; i++ {
            pub.x[i] = (C.uint32_t)(xl[i])
            pub.l[i] = (C.uint32_t)(xl[i+9])
        }
        return pub, nil
    }
    

Documentation

Index

Constants

View Source
const (
	// 64-byte (r, s) format
	Secp256k1SigSize = 64

	// 65-byte (r, s, v) format, where v is the recovery id
	Secp256k1SigSizeWithRecID = 65
)

const

Variables

View Source
var (
	// ErrInvalidKey is the error that the key format is invalid
	ErrInvalidKey = errors.New("invalid key format")
	// ErrPublicKey indicates the error of public key
	ErrPublicKey = errors.New("invalid public key")
	// ErrPrivateKey indicates the error of private key
	ErrPrivateKey = errors.New("invalid private key")
)
View Source
var (
	// CryptoSeed is a hardcoded seed that will be replaced by a seed produced dynamically.
	CryptoSeed = []byte{0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef}
)

Functions

func Sort added in v0.1.1

func Sort(hashes [][]byte, nonce uint64)

Sort sorts a given slices of hashes cryptographically using hash function

func SortCandidates added in v0.1.1

func SortCandidates(candidates []string, epochNum uint64, cryptoSeed []byte)

SortCandidates sorts a given slices of hashes cryptographically using hash function

func UpdatePrivateKeyPasswordToPem added in v0.1.2

func UpdatePrivateKeyPasswordToPem(fileName string, oldPwd string, newPwd string) error

UpdatePrivateKeyPasswordToPem updates private key's password for PEM file

func WritePrivateKeyToPem added in v0.1.2

func WritePrivateKeyToPem(file string, key *P256sm2PrvKey, pwd string) error

WritePrivateKeyToPem writes the private key to PEM file

func WritePublicKeyToPem added in v0.1.2

func WritePublicKeyToPem(file string, key *P256sm2PubKey, pwd string) error

WritePublicKeyToPem writes the public key to PEM file

Types

type Merkle added in v0.1.1

type Merkle struct {
	// contains filtered or unexported fields
}

Merkle tree struct

func NewMerkleTree added in v0.1.1

func NewMerkleTree(leaves []hash.Hash256) *Merkle

NewMerkleTree creates a merkle tree given hashed leaves

func (*Merkle) HashTree added in v0.1.1

func (mk *Merkle) HashTree() hash.Hash256

HashTree calculates the root hash of a merkle tree

type P256sm2PrvKey added in v0.1.2

type P256sm2PrvKey struct {
	*sm2.PrivateKey
}

P256sm2PrvKey implements the P256sm2 private key

func (*P256sm2PrvKey) Bytes added in v0.1.2

func (k *P256sm2PrvKey) Bytes() []byte

Bytes returns the private key in bytes representation

func (*P256sm2PrvKey) D added in v0.1.2

func (k *P256sm2PrvKey) D() []byte

D returns the secret D in big-endian

func (*P256sm2PrvKey) EcdsaPrivateKey added in v0.1.2

func (k *P256sm2PrvKey) EcdsaPrivateKey() interface{}

EcdsaPrivateKey returns the embedded ecdsa private key

func (*P256sm2PrvKey) HexString added in v0.1.2

func (k *P256sm2PrvKey) HexString() string

HexString returns the private key in hex string

func (*P256sm2PrvKey) PublicKey added in v0.1.2

func (k *P256sm2PrvKey) PublicKey() PublicKey

PublicKey returns the public key corresponding to private key

func (*P256sm2PrvKey) Sign added in v0.1.2

func (k *P256sm2PrvKey) Sign(hash []byte) ([]byte, error)

Sign signs the message/hash

func (*P256sm2PrvKey) Zero added in v0.1.2

func (k *P256sm2PrvKey) Zero()

Zero zeroes the private key data

type P256sm2PubKey added in v0.1.2

type P256sm2PubKey struct {
	*sm2.PublicKey
}

P256sm2PubKey implements the P256sm2 public key

func (*P256sm2PubKey) Address added in v0.1.5

func (k *P256sm2PubKey) Address() address.Address

Address returns the address object

func (*P256sm2PubKey) Bytes added in v0.1.2

func (k *P256sm2PubKey) Bytes() []byte

Bytes returns the public key in bytes representation

func (*P256sm2PubKey) EcdsaPublicKey added in v0.1.2

func (k *P256sm2PubKey) EcdsaPublicKey() interface{}

EcdsaPublicKey returns the embedded ecdsa publick key

func (*P256sm2PubKey) Hash added in v0.1.2

func (k *P256sm2PubKey) Hash() []byte

Hash is the last 20-byte of keccak hash of public key (X, Y) co-ordinate

func (*P256sm2PubKey) HexString added in v0.1.2

func (k *P256sm2PubKey) HexString() string

HexString returns the public key in hex string

func (*P256sm2PubKey) Verify added in v0.1.2

func (k *P256sm2PubKey) Verify(hash, sig []byte) bool

Verify verifies the signature

type PrivateKey

type PrivateKey interface {
	Bytes() []byte
	HexString() string
	EcdsaPrivateKey() interface{}
	PublicKey() PublicKey
	Sign([]byte) ([]byte, error)
	Zero()
}

PrivateKey represents a private key

func BytesToPrivateKey

func BytesToPrivateKey(prvKey []byte) (PrivateKey, error)

BytesToPrivateKey converts a byte slice to SECP256K1 PrivateKey

func GenerateKey

func GenerateKey() (PrivateKey, error)

GenerateKey generates a SECP256k1 PrivateKey

func GenerateKeySm2 added in v0.1.2

func GenerateKeySm2() (PrivateKey, error)

GenerateKeySm2 generates a P256sm2 PrivateKey

func HexStringToPrivateKey

func HexStringToPrivateKey(prvKey string) (PrivateKey, error)

HexStringToPrivateKey decodes a string to PrivateKey

func KeystoreToPrivateKey

func KeystoreToPrivateKey(account accounts.Account, password string) (PrivateKey, error)

KeystoreToPrivateKey generates PrivateKey from Keystore account

func ReadPrivateKeyFromPem added in v0.1.2

func ReadPrivateKeyFromPem(file string, pwd string) (PrivateKey, error)

ReadPrivateKeyFromPem reads the private key from PEM file

type PublicKey

type PublicKey interface {
	Bytes() []byte
	HexString() string
	EcdsaPublicKey() interface{}
	Hash() []byte
	Verify([]byte, []byte) bool
	Address() address.Address
}

PublicKey represents a public key

func BytesToPublicKey

func BytesToPublicKey(pubKey []byte) (PublicKey, error)

BytesToPublicKey converts a byte slice to SECP256K1 PublicKey

func HexStringToPublicKey

func HexStringToPublicKey(pubKey string) (PublicKey, error)

HexStringToPublicKey decodes a string to PublicKey

func ReadPublicKeyFromPem added in v0.1.2

func ReadPublicKeyFromPem(file string, pwd string) (PublicKey, error)

ReadPublicKeyFromPem reads the public key from PEM file

func RecoverPubkey added in v0.1.2

func RecoverPubkey(msg, sig []byte) (PublicKey, error)

RecoverPubkey recovers the public key from signature

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL