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 }