github.com/klaytn/klaytn@v1.12.1/crypto/bls/blst/vector_test.go (about)

     1  package blst
     2  
     3  import (
     4  	"archive/tar"
     5  	"compress/gzip"
     6  	"encoding/json"
     7  	"io"
     8  	"os"
     9  	"path"
    10  	"testing"
    11  
    12  	"github.com/klaytn/klaytn/common"
    13  	"github.com/stretchr/testify/assert"
    14  )
    15  
    16  // Use the file downloaded according to https://github.com/ethereum/bls12-381-tests
    17  // TESTS_VERSION=v0.1.2
    18  // wget https://github.com/ethereum/bls12-381-tests/releases/download/${TESTS_VERSION}/bls_tests_json.tar.gz
    19  
    20  type testVectorChecker func(t *testing.T, name string, vectorJson []byte)
    21  
    22  func TestVectors(t *testing.T) {
    23  	checkers := map[string]testVectorChecker{
    24  		"aggregate/":             checkAggregate,
    25  		"batch_verify/":          checkBatchVerify,
    26  		"deserialization_G1/":    checkDeserializationG1,
    27  		"deserialization_G2/":    checkDeserializationG2,
    28  		"fast_aggregate_verify/": checkFastAggregateVerify,
    29  		"sign/":                  checkSign,
    30  		"verify/":                checkVerify,
    31  	}
    32  
    33  	// If some test vectors cannot pass, list below with a reason.
    34  	exemptions := map[string]bool{
    35  		// PublicKeyFromBytes rejects inifinity point via KeyValidate()
    36  		"deserialization_G1/deserialization_succeeds_infinity_with_true_b_flag.json": true,
    37  		// AggregateVerify(asig, msgs, pks) not implemented
    38  		"aggregate_verify/aggregate_verify_infinity_pubkey.json":                   true,
    39  		"aggregate_verify/aggregate_verify_na_pubkeys_and_infinity_signature.json": true,
    40  		"aggregate_verify/aggregate_verify_na_pubkeys_and_na_signature.json":       true,
    41  		"aggregate_verify/aggregate_verify_tampered_signature.json":                true,
    42  		"aggregate_verify/aggregate_verify_valid.json":                             true,
    43  		// Low-level HashToG2 not implemented
    44  		"hash_to_G2/hash_to_G2__2782afaa8406d038.json": true,
    45  		"hash_to_G2/hash_to_G2__7590bd067999bbfb.json": true,
    46  		"hash_to_G2/hash_to_G2__a54942c8e365f378.json": true,
    47  		"hash_to_G2/hash_to_G2__c938b486cf69e8f7.json": true,
    48  	}
    49  
    50  	f, err := os.Open("./bls_tests_json.tar.gz")
    51  	if err != nil {
    52  		t.Fatal(err)
    53  	}
    54  	defer f.Close()
    55  
    56  	stream, err := gzip.NewReader(f)
    57  	reader := tar.NewReader(stream)
    58  
    59  	for {
    60  		header, err := reader.Next()
    61  		if err == io.EOF {
    62  			break
    63  		} else if err != nil {
    64  			t.Fatal(err)
    65  		}
    66  
    67  		switch header.Typeflag {
    68  		case tar.TypeReg:
    69  			name := path.Clean(header.Name)
    70  			dir, _ := path.Split(name)
    71  			if exemptions[name] {
    72  				t.Logf("skip  %s", name)
    73  				continue
    74  			}
    75  
    76  			checker := checkers[dir]
    77  			if checker == nil {
    78  				t.Fatalf("unrecognized vector file: %s", header.Name)
    79  				// continue
    80  			}
    81  
    82  			data, err := io.ReadAll(reader)
    83  			if err != nil {
    84  				t.Fatal(err)
    85  			}
    86  
    87  			t.Logf("check %s", name)
    88  			checker(t, name, data)
    89  		}
    90  	}
    91  }
    92  
    93  func checkAggregate(t *testing.T, name string, vectorJson []byte) {
    94  	vector := struct {
    95  		Input  []string
    96  		Output *string
    97  	}{}
    98  	if err := json.Unmarshal(vectorJson, &vector); err != nil {
    99  		t.Fatal(err)
   100  	}
   101  
   102  	sigbs := fromHexBatch(vector.Input)
   103  	asig, err := AggregateSignaturesFromBytes(sigbs)
   104  	if vector.Output != nil {
   105  		asigb := common.FromHex(*vector.Output)
   106  		assert.Nil(t, err)
   107  		assert.Equal(t, asigb, asig.Marshal())
   108  	} else {
   109  		assert.NotNil(t, err)
   110  	}
   111  }
   112  
   113  func checkBatchVerify(t *testing.T, name string, vectorJson []byte) {
   114  	vector := struct {
   115  		Input struct {
   116  			Pubkeys    []string
   117  			Messages   []string
   118  			Signatures []string
   119  		}
   120  		Output bool
   121  	}{}
   122  	if err := json.Unmarshal(vectorJson, &vector); err != nil {
   123  		t.Fatal(err)
   124  	}
   125  
   126  	var (
   127  		pkbs      = fromHexBatch(vector.Input.Pubkeys)
   128  		msgs      = fromHexBatch32(vector.Input.Messages)
   129  		sigbs     = fromHexBatch(vector.Input.Signatures)
   130  		pks, err1 = MultiplePublicKeysFromBytes(pkbs)
   131  		ok, err2  = VerifyMultipleSignatures(sigbs, msgs, pks)
   132  	)
   133  	if vector.Output == true {
   134  		assert.Nil(t, err1, name)
   135  		assert.Nil(t, err2, name)
   136  		assert.True(t, ok, name)
   137  	} else {
   138  		// At least an error or verify false.
   139  		assert.True(t, (err1 != nil || err2 != nil || !ok), name)
   140  	}
   141  }
   142  
   143  func checkFastAggregateVerify(t *testing.T, name string, vectorJson []byte) {
   144  	vector := struct {
   145  		Input struct {
   146  			Pubkeys   []string
   147  			Message   string
   148  			Signature string
   149  		}
   150  		Output bool
   151  	}{}
   152  	if err := json.Unmarshal(vectorJson, &vector); err != nil {
   153  		t.Fatal(err)
   154  	}
   155  
   156  	var (
   157  		pkbs      = fromHexBatch(vector.Input.Pubkeys)
   158  		msg       = common.FromHex(vector.Input.Message)
   159  		sigb      = common.FromHex(vector.Input.Signature)
   160  		apk, err1 = AggregatePublicKeysFromBytes(pkbs)
   161  		sig, err2 = SignatureFromBytes(sigb)
   162  		ok        = false
   163  	)
   164  	if err1 == nil && err2 == nil {
   165  		ok = Verify(sig, msg, apk)
   166  	}
   167  
   168  	if vector.Output == true {
   169  		assert.Nil(t, err1, name)
   170  		assert.Nil(t, err2, name)
   171  		assert.True(t, ok, name)
   172  	} else {
   173  		// At least an error or verify false.
   174  		assert.True(t, (err1 != nil || err2 != nil || !ok), name)
   175  	}
   176  }
   177  
   178  func checkDeserializationG1(t *testing.T, name string, vectorJson []byte) {
   179  	vector := struct {
   180  		Input  struct{ Pubkey string }
   181  		Output bool
   182  	}{}
   183  	if err := json.Unmarshal(vectorJson, &vector); err != nil {
   184  		t.Fatal(err)
   185  	}
   186  
   187  	b := common.FromHex(vector.Input.Pubkey)
   188  	pk, err := PublicKeyFromBytes(b)
   189  	if vector.Output == true {
   190  		assert.Nil(t, err, name)
   191  		assert.Equal(t, b, pk.Marshal(), name)
   192  	} else {
   193  		assert.NotNil(t, err, name)
   194  	}
   195  }
   196  
   197  func checkDeserializationG2(t *testing.T, name string, vectorJson []byte) {
   198  	vector := struct {
   199  		Input  struct{ Signature string }
   200  		Output bool
   201  	}{}
   202  	if err := json.Unmarshal(vectorJson, &vector); err != nil {
   203  		t.Fatal(err)
   204  	}
   205  
   206  	b := common.FromHex(vector.Input.Signature)
   207  	sig, err := SignatureFromBytes(b)
   208  	if vector.Output == true {
   209  		assert.Nil(t, err, name)
   210  		assert.Equal(t, b, sig.Marshal(), name)
   211  	} else {
   212  		assert.NotNil(t, err, name)
   213  	}
   214  }
   215  
   216  func checkSign(t *testing.T, name string, vectorJson []byte) {
   217  	vector := struct {
   218  		Input struct {
   219  			Privkey string
   220  			Message string
   221  		}
   222  		Output *string
   223  	}{}
   224  	if err := json.Unmarshal(vectorJson, &vector); err != nil {
   225  		t.Fatal(err)
   226  	}
   227  
   228  	skb := common.FromHex(vector.Input.Privkey)
   229  	msg := common.FromHex(vector.Input.Message)
   230  
   231  	sk, err := SecretKeyFromBytes(skb)
   232  	if vector.Output != nil {
   233  		sigb := common.FromHex(*vector.Output)
   234  		assert.Nil(t, err, name)
   235  		assert.Equal(t, sigb, Sign(sk, msg).Marshal(), name)
   236  	} else {
   237  		assert.NotNil(t, err, name)
   238  	}
   239  }
   240  
   241  func checkVerify(t *testing.T, name string, vectorJson []byte) {
   242  	vector := struct {
   243  		Input struct {
   244  			Pubkey    string
   245  			Message   string
   246  			Signature string
   247  		}
   248  		Output bool
   249  	}{}
   250  	if err := json.Unmarshal(vectorJson, &vector); err != nil {
   251  		t.Fatal(err)
   252  	}
   253  
   254  	var (
   255  		pkb       = common.FromHex(vector.Input.Pubkey)
   256  		msg       = common.FromHex(vector.Input.Message)
   257  		sigb      = common.FromHex(vector.Input.Signature)
   258  		pk, err1  = PublicKeyFromBytes(pkb)
   259  		sig, err2 = SignatureFromBytes(sigb)
   260  		ok        = false
   261  	)
   262  	if err1 == nil && err2 == nil {
   263  		ok = Verify(sig, msg, pk)
   264  	}
   265  
   266  	if vector.Output == true {
   267  		assert.Nil(t, err1, name)
   268  		assert.Nil(t, err2, name)
   269  		assert.True(t, ok, name)
   270  	} else {
   271  		// At least an error or verify false.
   272  		assert.True(t, (err1 != nil || err2 != nil || !ok), name)
   273  	}
   274  }
   275  
   276  func fromHexBatch(sArr []string) [][]byte {
   277  	bArr := make([][]byte, len(sArr))
   278  	for i, s := range sArr {
   279  		bArr[i] = common.FromHex(s)
   280  	}
   281  	return bArr
   282  }
   283  
   284  func fromHexBatch32(sArr []string) [][32]byte {
   285  	bArr := make([][32]byte, len(sArr))
   286  	for i, s := range sArr {
   287  		copy(bArr[i][:], common.FromHex(s))
   288  	}
   289  	return bArr
   290  }