Skip to content

Commit

Permalink
Merge branch 'release/v1.4.2'
Browse files Browse the repository at this point in the history
  • Loading branch information
quvox committed Aug 2, 2019
2 parents 7f7455a + 01c4571 commit bb2152a
Show file tree
Hide file tree
Showing 7 changed files with 188 additions and 76 deletions.
11 changes: 7 additions & 4 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
CHANGELOG
====

### v1.4.1
## v1.4.2
* Add key import/export functions in keypair.go

## v1.4.1
* Add installation script (prepare_bbclib.sh)

### v1.4
## v1.4
* ID length configuration support (same as py-bbclib v1.4.1)
* External public key support (same as py-bbclib v1.4.1)
* BBcSignature having 0-length public key indicates that the public key for verification is given externally.

### v1.3
## v1.3
* not released

# v1.2
## v1.2
* Golang implementation of bbclib.py in BBc-1 version 1.2
- Cloned from quvox/bbclib-go

4 changes: 2 additions & 2 deletions bbclib_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,8 @@ func makeFollowTXWithUtility(refTxObj *BBcTransaction) *BBcTransaction {

func TestBBcLibUtilitiesTx1(t *testing.T) {
assetGroupID = GetIdentifierWithTimestamp("assetGroupID", defaultIDLength)
keypair1 = GenerateKeypair(KeyTypeEcdsaP256v1, defaultCompressionMode)
keypair2 = GenerateKeypair(KeyTypeEcdsaSECP256k1, defaultCompressionMode)
keypair1 = GenerateKeypair(KeyTypeEcdsaP256v1, DefaultCompressionMode)
keypair2 = GenerateKeypair(KeyTypeEcdsaSECP256k1, DefaultCompressionMode)

t.Run("MakeTransaction and events", func(t *testing.T) {
txobj = MakeTransaction(3, 0, true)
Expand Down
100 changes: 92 additions & 8 deletions keypair.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,10 @@ This object includes functions for sign and verify a signature. The sign/verify
*/
type (
KeyPair struct {
CurveType int
Pubkey []byte
Privkey []byte
CurveType int
CompressionType int
Pubkey []byte
Privkey []byte
}
)

Expand All @@ -44,7 +45,7 @@ const (
KeyTypeEcdsaSECP256k1 = 1
KeyTypeEcdsaP256v1 = 2

defaultCompressionMode = 4
DefaultCompressionMode = 4
)

// GenerateKeypair generates a new Key pair object with new private key and public key
Expand All @@ -57,18 +58,73 @@ func GenerateKeypair(curveType int, compressionMode int) KeyPair {
return KeyPair{CurveType: curveType, Pubkey: pubkey[:lenPubkey], Privkey: privkey[:lenPrivkey]}
}

// ConvertFromPem outputs PEM formatted public key
// GetPublicKeyUncompressed gets a public key (uncompressed) from private key
func (k *KeyPair) GetPublicKeyUncompressed() *[]byte {
var lenPubkey C.int
pubkey := make([]byte, 100)
C.get_public_key_uncompressed(C.int(k.CurveType), C.int(len(k.Privkey)),
(*C.uint8_t)(unsafe.Pointer(&k.Privkey[0])),
&lenPubkey, (*C.uint8_t)(unsafe.Pointer(&pubkey[0])))
k.Pubkey = pubkey[:lenPubkey]
return &k.Pubkey
}

// GetPublicKeyCompressed gets a public key (compressed) from private key
func (k *KeyPair) GetPublicKeyCompressed() *[]byte {
var lenPubkey C.int
pubkey := make([]byte, 100)
C.get_public_key_compressed(C.int(k.CurveType), C.int(len(k.Privkey)),
(*C.uint8_t)(unsafe.Pointer(&k.Privkey[0])),
&lenPubkey, (*C.uint8_t)(unsafe.Pointer(&pubkey[0])))
k.Pubkey = pubkey[:lenPubkey]
return &k.Pubkey
}


// ConvertFromPem imports PEM formatted private key
func (k *KeyPair) ConvertFromPem(pem string, compressionMode int) {
pubkey := make([]byte, 100)
privkey := make([]byte, 100)
pemstr := ([]byte)(pem)
pemByte := ([]byte)(pem)

var lenPubkey, lenPrivkey C.int
C.convert_from_pem((*C.char)(unsafe.Pointer(&pemByte[0])), (C.uint8_t)(compressionMode),
&lenPubkey, (*C.uint8_t)(unsafe.Pointer(&pubkey[0])),
&lenPrivkey, (*C.uint8_t)(unsafe.Pointer(&privkey[0])))
k.Pubkey = pubkey[:lenPubkey]
k.Privkey = privkey[:lenPrivkey]
}

// ConvertFromPem imports DER formatted private key
func (k *KeyPair) ConvertFromDer(der []byte, compressionMode int) {
pubkey := make([]byte, 100)
privkey := make([]byte, 100)

var lenPubkey, lenPrivkey C.int
C.convert_from_pem((*C.char)(unsafe.Pointer(&pemstr[0])), (C.uint8_t)(compressionMode),
C.convert_from_der(C.long(len(der)), (*C.uint8_t)(unsafe.Pointer(&der[0])), (C.uint8_t)(compressionMode),
&lenPubkey, (*C.uint8_t)(unsafe.Pointer(&pubkey[0])),
&lenPrivkey, (*C.uint8_t)(unsafe.Pointer(&privkey[0])))
k.Pubkey = pubkey[:lenPubkey]
k.Privkey = pubkey[:lenPrivkey]
k.Privkey = privkey[:lenPrivkey]
}

// ReadX509 imports X.509 public key certificate
func (k *KeyPair) ReadX509(cert string, compressionMode int) {
pubkey := make([]byte, 100)
certByte := ([]byte)(cert)

var lenPubkey C.int
C.read_x509((*C.char)(unsafe.Pointer(&certByte[0])), (C.uint8_t)(compressionMode),
&lenPubkey, (*C.uint8_t)(unsafe.Pointer(&pubkey[0])))
k.Pubkey = pubkey[:lenPubkey]
}

// VerifyX509 verifies the public key's legitimacy
func (k *KeyPair) CheckX509(cert string, privkey string) bool {
certByte := ([]byte)(cert)
privkeyByte := ([]byte)(privkey)
result := C.verify_x509( (*C.char)(unsafe.Pointer(&certByte[0])), (*C.char)(unsafe.Pointer(&privkeyByte[0])))
return result == 1
}

// Sign to a given digest
Expand Down Expand Up @@ -109,6 +165,34 @@ func (k *KeyPair) Verify(digest []byte, sig []byte) bool {
return result == 1
}

// OutputDer outputs DER formatted private key
func (k *KeyPair) OutputDer() []byte {
der := make([]byte, 1024)
C.output_der(C.int(k.CurveType), C.int(len(k.Privkey)), (*C.uint8_t)(unsafe.Pointer(&k.Privkey[0])), (*C.uint8_t)(unsafe.Pointer(&der[0])))
return der
}

// OutputDer outputs PEM formatted private key
func (k *KeyPair) OutputPem() string {
pem := make([]byte, 2048)
C.output_pem(C.int(k.CurveType), C.int(len(k.Privkey)), (*C.uint8_t)(unsafe.Pointer(&k.Privkey[0])), (*C.uint8_t)(unsafe.Pointer(&pem[0])))
return string(pem)
}

// OutputDer outputs DER formatted private key
func (k *KeyPair) OutputPublicKeyDer() []byte {
der := make([]byte, 8192)
C.output_public_key_der(C.int(k.CurveType), C.int(len(k.Pubkey)), (*C.uint8_t)(unsafe.Pointer(&k.Pubkey[0])), (*C.uint8_t)(unsafe.Pointer(&der[0])))
return der
}

// OutputDer outputs PEM formatted private key
func (k *KeyPair) OutputPublicKeyPem() string {
pem := make([]byte, 32768)
C.output_public_key_pem(C.int(k.CurveType), C.int(len(k.Pubkey)), (*C.uint8_t)(unsafe.Pointer(&k.Pubkey[0])), (*C.uint8_t)(unsafe.Pointer(&pem[0])))
return string(pem)
}

// VerifyBBcSignature verifies a given digest with BBcSignature object
func VerifyBBcSignature(digest []byte, sig *BBcSignature) bool {
result := C.verify(C.int(sig.KeyType), C.int(len(sig.Pubkey)), (*C.uint8_t)(unsafe.Pointer(&sig.Pubkey[0])),
Expand Down
37 changes: 31 additions & 6 deletions keypair_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,14 @@ package bbclib

import (
"crypto/sha256"
"bytes"
"testing"
)

func TestGenerateKeypair(t *testing.T) {
for curvetype := 1; curvetype < 3; curvetype++ {
t.Run("curvetype", func(t *testing.T) {
keypair := GenerateKeypair(curvetype, defaultCompressionMode)
keypair := GenerateKeypair(curvetype, DefaultCompressionMode)
t.Logf("keypair: %v", keypair)
if len(keypair.Pubkey) != 65 {
t.Fatal("fail to generate keypair")
Expand All @@ -40,8 +41,8 @@ func TestKeyPair_Sign_and_Verify(t *testing.T) {
t.Logf("SHA-256 digest2: %x\n", digest2)

for curvetype := 1; curvetype < 3; curvetype++ {
keypair := GenerateKeypair(curvetype, defaultCompressionMode)
keypair2 := GenerateKeypair(curvetype, defaultCompressionMode)
keypair := GenerateKeypair(curvetype, DefaultCompressionMode)
keypair2 := GenerateKeypair(curvetype, DefaultCompressionMode)
t.Run("curvetype", func(t *testing.T) {
t.Logf("Curvetype = %d", curvetype)
if len(keypair.Pubkey) != 65 {
Expand Down Expand Up @@ -101,7 +102,7 @@ func TestVerifyBBcSignature(t *testing.T) {

for curvetype := 1; curvetype < 3; curvetype++ {
t.Run("curvetype", func(t *testing.T) {
keypair := GenerateKeypair(curvetype, defaultCompressionMode)
keypair := GenerateKeypair(curvetype, DefaultCompressionMode)
sig := BBcSignature{}
sig.SetPublicKey(uint32(curvetype), &keypair.Pubkey)
signature := keypair.Sign(digest[:])
Expand All @@ -118,7 +119,7 @@ func TestVerifyBBcSignature(t *testing.T) {
}
t.Log("Verify succeeded")

keypair2 := GenerateKeypair(curvetype, defaultCompressionMode)
keypair2 := GenerateKeypair(curvetype, DefaultCompressionMode)
sig2 := BBcSignature{}
sig2.SetPublicKey(uint32(curvetype), &keypair.Pubkey)
signature2 := keypair2.Sign(digest[:])
Expand All @@ -135,11 +136,35 @@ func TestVerifyBBcSignature(t *testing.T) {
func TestKeyPair_ConvertFromPem(t *testing.T) {
pem := "-----BEGIN EC PRIVATE KEY-----\nMHQCAQEEIIMVMPKLJqivgRDpRDaWJCOnob6s/+t4MdoFN/8PVkNSoAcGBSuBBAAK\noUQDQgAE/k1ZM/Ker1+N0+Lg5za0sJZeSAAeYwDEWnkgnkCynErs74G/tAnu/lcu\nk8kzAivYm8mitIpJJw1OdjCDJI457g==\n-----END EC PRIVATE KEY-----"
keypair := KeyPair{CurveType: KeyTypeEcdsaSECP256k1}
keypair.ConvertFromPem(pem, defaultCompressionMode)
keypair.ConvertFromPem(pem, DefaultCompressionMode)
t.Logf("keypair: %v", keypair)

if len(keypair.Privkey) != 32 {
t.Fatal("failed to read private key in pem format")
}
t.Logf("private key: %x", keypair.Privkey)
}

func TestKeyPair_OutputKey(t *testing.T) {
keypair := GenerateKeypair(KeyTypeEcdsaP256v1, DefaultCompressionMode)
der := keypair.OutputDer()
pem := keypair.OutputPem()

keypair2 := KeyPair{CurveType: KeyTypeEcdsaP256v1}
keypair2.ConvertFromDer(der, DefaultCompressionMode)
if bytes.Compare(keypair.Privkey, keypair2.Privkey) != 0 {
t.Fatal("export or import is failed (DER)")
}

pubkey2 := keypair2.GetPublicKeyCompressed()
t.Logf("public key (compressed): %v", pubkey2)

keypair3 := KeyPair{CurveType: KeyTypeEcdsaP256v1}
keypair3.ConvertFromPem(pem, DefaultCompressionMode)
if bytes.Compare(keypair.Privkey, keypair3.Privkey) != 0 {
t.Fatal("export or import is failed (PEM)")
}

pubkey3 := keypair3.GetPublicKeyCompressed()
t.Logf("public key (compressed): %v", pubkey3)
}
4 changes: 2 additions & 2 deletions signature_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import (
func TestSignaturePackUnpack(t *testing.T) {

t.Run("simple creation (set by keypair)", func(t *testing.T) {
keypair := GenerateKeypair(KeyTypeEcdsaP256v1, defaultCompressionMode)
keypair := GenerateKeypair(KeyTypeEcdsaP256v1, DefaultCompressionMode)
sig := BBcSignature{}
sig.SetPublicKeyByKeypair(&keypair)
signature := GetRandomValue(64)
Expand Down Expand Up @@ -79,7 +79,7 @@ func TestSignaturePackUnpack(t *testing.T) {
})

t.Run("simple creation (external public key for verification)", func(t *testing.T) {
keypair := GenerateKeypair(KeyTypeEcdsaP256v1, defaultCompressionMode)
keypair := GenerateKeypair(KeyTypeEcdsaP256v1, DefaultCompressionMode)
sig := BBcSignature{}
sig.SetPublicKeyInfo(KeyTypeEcdsaP256v1)
digest := GetRandomValue(64)
Expand Down

0 comments on commit bb2152a

Please sign in to comment.