github.com/cloudflare/circl@v1.5.0/abe/cpabe/tkn20/bench_test.go (about)

     1  package tkn20
     2  
     3  import (
     4  	"crypto/rand"
     5  	"crypto/rsa"
     6  	"crypto/x509"
     7  	"fmt"
     8  	"strconv"
     9  	"strings"
    10  	"testing"
    11  
    12  	"golang.org/x/crypto/nacl/box"
    13  )
    14  
    15  type abeTestCase struct {
    16  	desc   string
    17  	attrs  Attributes
    18  	policy Policy
    19  	msk    SystemSecretKey
    20  	pk     PublicKey
    21  }
    22  
    23  var testCases []abeTestCase
    24  
    25  var (
    26  	msg     = []byte("drink your ovaltine now")
    27  	longMsg = []byte(strings.Repeat("a", 10000))
    28  )
    29  
    30  func generateAttrs() Attributes {
    31  	benchableAttrs := make(map[string]string, 50)
    32  	for i := 0; i < 50; i++ {
    33  		benchableAttrs["k"+strconv.Itoa(i)] = "v" + strconv.Itoa(i)
    34  	}
    35  	attrs := Attributes{}
    36  	attrs.FromMap(benchableAttrs)
    37  	return attrs
    38  }
    39  
    40  func generatePolicy() string {
    41  	var policyBuilder strings.Builder
    42  	for i := 0; i < 50; i++ {
    43  		policyBuilder.WriteString("k")
    44  		policyBuilder.WriteString(strconv.Itoa(i))
    45  		policyBuilder.WriteString(":v")
    46  		policyBuilder.WriteString(strconv.Itoa(i))
    47  		if i != 49 {
    48  			if i%2 == 0 {
    49  				policyBuilder.WriteString(" and ")
    50  			} else {
    51  				policyBuilder.WriteString(" or ")
    52  			}
    53  		}
    54  	}
    55  	return policyBuilder.String()
    56  }
    57  
    58  func init() {
    59  	smallPolicy := Policy{}
    60  	_ = smallPolicy.FromString("(k1:v1 or k1:v2) and not k2:v3")
    61  	smallAttrs := Attributes{}
    62  	smallAttrs.FromMap(map[string]string{"k1": "v2", "k2": "v4"})
    63  	longPolicy := Policy{}
    64  	_ = longPolicy.FromString(generatePolicy())
    65  	testCases = []abeTestCase{
    66  		{
    67  			desc:   "smallPolicy/Attrs",
    68  			attrs:  smallAttrs,
    69  			policy: smallPolicy,
    70  		},
    71  		{
    72  			desc:   "longPolicy/Attrs",
    73  			attrs:  generateAttrs(),
    74  			policy: longPolicy,
    75  		},
    76  	}
    77  	var err error
    78  	for i := range testCases {
    79  		testCases[i].pk, testCases[i].msk, err = Setup(rand.Reader)
    80  		if err != nil {
    81  			panic(err)
    82  		}
    83  	}
    84  }
    85  
    86  func BenchmarkTKN20KeyGen(b *testing.B) {
    87  	for _, tc := range testCases {
    88  		b.Run(fmt.Sprintf("keygen:%s", tc.desc), func(b *testing.B) {
    89  			b.ResetTimer()
    90  			for i := 0; i < b.N; i++ {
    91  				_, err := tc.msk.KeyGen(rand.Reader, tc.attrs)
    92  				if err != nil {
    93  					b.Fatal(err)
    94  				}
    95  			}
    96  		})
    97  	}
    98  }
    99  
   100  func BenchmarkRSAKeyGen(b *testing.B) {
   101  	for i := 0; i < b.N; i++ {
   102  		_, err := rsa.GenerateKey(rand.Reader, 2048)
   103  		if err != nil {
   104  			b.Fatal(err)
   105  		}
   106  	}
   107  }
   108  
   109  func BenchmarkX25519KeyGen(b *testing.B) {
   110  	for i := 0; i < b.N; i++ {
   111  		_, _, err := box.GenerateKey(rand.Reader)
   112  		if err != nil {
   113  			b.Fatal(err)
   114  		}
   115  	}
   116  }
   117  
   118  func BenchmarkTKN20Encrypt(b *testing.B) {
   119  	for _, tc := range testCases {
   120  		b.Run(fmt.Sprintf("encrypt:%s", tc.desc), func(b *testing.B) {
   121  			b.ResetTimer()
   122  			for i := 0; i < b.N; i++ {
   123  				_, err := tc.pk.Encrypt(rand.Reader, tc.policy, msg)
   124  				if err != nil {
   125  					b.Fatal(err)
   126  				}
   127  			}
   128  		})
   129  	}
   130  }
   131  
   132  func BenchmarkRSAEncrypt(b *testing.B) {
   133  	privKey, err := rsa.GenerateKey(rand.Reader, 2048)
   134  	if err != nil {
   135  		b.Fatal(err)
   136  	}
   137  	pubKey := privKey.PublicKey
   138  	b.ResetTimer()
   139  	for i := 0; i < b.N; i++ {
   140  		_, err := rsa.EncryptPKCS1v15(rand.Reader, &pubKey, msg)
   141  		if err != nil {
   142  			b.Fatal(err)
   143  		}
   144  	}
   145  }
   146  
   147  func BenchmarkX25519Encrypt(b *testing.B) {
   148  	pubKey, _, err := box.GenerateKey(rand.Reader)
   149  	if err != nil {
   150  		b.Fatal(err)
   151  	}
   152  	b.ResetTimer()
   153  	for i := 0; i < b.N; i++ {
   154  		_, err := box.SealAnonymous(nil, msg, pubKey, rand.Reader)
   155  		if err != nil {
   156  			b.Fatal(err)
   157  		}
   158  	}
   159  }
   160  
   161  func BenchmarkTKN20Decrypt(b *testing.B) {
   162  	for _, tc := range testCases {
   163  		b.Run(fmt.Sprintf("decrypt:%s", tc.desc), func(b *testing.B) {
   164  			userKey, err := tc.msk.KeyGen(rand.Reader, tc.attrs)
   165  			if err != nil {
   166  				b.Fatal(err)
   167  			}
   168  			ciphertext, err := tc.pk.Encrypt(rand.Reader, tc.policy, msg)
   169  			if err != nil {
   170  				b.Fatal(err)
   171  			}
   172  			keyBytes, _ := userKey.MarshalBinary()
   173  			pubKeyBytes, _ := tc.pk.MarshalBinary()
   174  			// longCt is only benchmarked to measure size overhead
   175  			longCt, err := tc.pk.Encrypt(rand.Reader, tc.policy, longMsg)
   176  			if err != nil {
   177  				b.Fatal(err)
   178  			}
   179  			b.ResetTimer()
   180  			for i := 0; i < b.N; i++ {
   181  				_, err = userKey.Decrypt(ciphertext)
   182  				if err != nil {
   183  					b.Fatal(err)
   184  				}
   185  			}
   186  			b.ReportMetric(float64(len(pubKeyBytes)), "public_key_size")
   187  			b.ReportMetric(float64(len(keyBytes)), "attribute_secret_key_size")
   188  			b.ReportMetric(float64(len(ciphertext)-len(msg)), "ciphertext_bytes_overhead_32b_msg")
   189  			b.ReportMetric(float64(len(longCt)-len(longMsg)), "ciphertext_bytes_overhead_10kb_msg")
   190  		})
   191  	}
   192  }
   193  
   194  func BenchmarkRSADecrypt(b *testing.B) {
   195  	privKey, err := rsa.GenerateKey(rand.Reader, 2048)
   196  	if err != nil {
   197  		b.Fatal(err)
   198  	}
   199  	pubKey := privKey.PublicKey
   200  	ct, err := rsa.EncryptPKCS1v15(rand.Reader, &pubKey, msg)
   201  	if err != nil {
   202  		b.Fatal(err)
   203  	}
   204  	// longCt is only benchmarked to measure size overhead
   205  	longCt, err := rsaEncrypt(longMsg, &privKey.PublicKey)
   206  	if err != nil {
   207  		b.Fatal(err)
   208  	}
   209  	b.ResetTimer()
   210  	for i := 0; i < b.N; i++ {
   211  		_, err := rsa.DecryptPKCS1v15(rand.Reader, privKey, ct)
   212  		if err != nil {
   213  			b.Fatal(err)
   214  		}
   215  	}
   216  	b.ReportMetric(float64(privKey.PublicKey.Size()), "public_key_size")
   217  	b.ReportMetric(float64(len(x509.MarshalPKCS1PrivateKey(privKey))), "secret_key_size")
   218  	b.ReportMetric(float64(len(ct)-len(msg)), "ciphertext_bytes_overhead")
   219  	b.ReportMetric(float64(len(longCt)-len(longMsg)), "ciphertext_bytes_overhead_10kb_msg")
   220  }
   221  
   222  func BenchmarkX25519Decrypt(b *testing.B) {
   223  	pubKey, privKey, err := box.GenerateKey(rand.Reader)
   224  	if err != nil {
   225  		b.Fatal(err)
   226  	}
   227  	ct, err := box.SealAnonymous(nil, msg, pubKey, rand.Reader)
   228  	if err != nil {
   229  		b.Fatal(err)
   230  	}
   231  	// longCt is only benchmarked to measure size overhead
   232  	longCt, err := box.SealAnonymous(nil, longMsg, pubKey, rand.Reader)
   233  	if err != nil {
   234  		b.Fatal(err)
   235  	}
   236  	b.ResetTimer()
   237  	for i := 0; i < b.N; i++ {
   238  		_, ok := box.OpenAnonymous(nil, ct, pubKey, privKey)
   239  		if !ok {
   240  			b.Fatal(err)
   241  		}
   242  	}
   243  	b.ReportMetric(float64(len(pubKey)), "public_key_size")
   244  	b.ReportMetric(float64(len(privKey)), "secret_key_size")
   245  	b.ReportMetric(float64(len(ct)-len(msg)), "ciphertext_bytes_overhead_32b_msg")
   246  	b.ReportMetric(float64(len(longCt)-len(longMsg)), "ciphertext_bytes_overhead_10kb_msg")
   247  }
   248  
   249  func rsaEncrypt(data []byte, pubKey *rsa.PublicKey) ([]byte, error) {
   250  	chunkSize := 245 // Max chunk size for 2048 bit key with PKCS1v15 padding
   251  	var ct []byte
   252  	for len(data) > 0 {
   253  		if len(data) < chunkSize {
   254  			chunkSize = len(data)
   255  		}
   256  		chunk := data[:chunkSize]
   257  		data = data[chunkSize:]
   258  		encryptedChunk, err := rsa.EncryptPKCS1v15(rand.Reader, pubKey, chunk)
   259  		if err != nil {
   260  			return nil, err
   261  		}
   262  		ct = append(ct, encryptedChunk...)
   263  	}
   264  	return ct, nil
   265  }