-
Notifications
You must be signed in to change notification settings - Fork 147
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
1 changed file
with
263 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,263 @@ | ||
package tkn20 | ||
|
||
import ( | ||
"crypto/rand" | ||
"crypto/rsa" | ||
"crypto/x509" | ||
"fmt" | ||
"golang.org/x/crypto/nacl/box" | ||
"strconv" | ||
"strings" | ||
"testing" | ||
//cpabe "github.com/cloudflare/circl/abe/cpabe/tkn20" | ||
) | ||
|
||
type abeTestCase struct { | ||
desc string | ||
attrs Attributes | ||
policy Policy | ||
msk SystemSecretKey | ||
pk PublicKey | ||
} | ||
|
||
var testCases []abeTestCase | ||
|
||
var msg = []byte("drink your ovaltine now") | ||
var longMsg = []byte(strings.Repeat("a", 10000)) | ||
|
||
func generateAttrs() Attributes { | ||
benchableAttrs := make(map[string]string, 50) | ||
for i := 0; i < 50; i++ { | ||
benchableAttrs["k"+strconv.Itoa(i)] = "v" + strconv.Itoa(i) | ||
} | ||
attrs := Attributes{} | ||
attrs.FromMap(benchableAttrs) | ||
return attrs | ||
} | ||
|
||
func generatePolicy() string { | ||
var policyBuilder strings.Builder | ||
for i := 0; i < 50; i++ { | ||
policyBuilder.WriteString("k") | ||
policyBuilder.WriteString(strconv.Itoa(i)) | ||
policyBuilder.WriteString(":v") | ||
policyBuilder.WriteString(strconv.Itoa(i)) | ||
if i != 49 { | ||
if i%2 == 0 { | ||
policyBuilder.WriteString(" and ") | ||
} else { | ||
policyBuilder.WriteString(" or ") | ||
} | ||
} | ||
} | ||
return policyBuilder.String() | ||
} | ||
|
||
func init() { | ||
smallPolicy := Policy{} | ||
smallPolicy.FromString("(k1:v1 or k1:v2) and not k2:v3") | ||
smallAttrs := Attributes{} | ||
smallAttrs.FromMap(map[string]string{"k1": "v2", "k2": "v4"}) | ||
longPolicy := Policy{} | ||
longPolicy.FromString(generatePolicy()) | ||
testCases = []abeTestCase{ | ||
{ | ||
desc: "smallPolicy/Attrs", | ||
attrs: smallAttrs, | ||
policy: smallPolicy, | ||
}, | ||
{ | ||
desc: "longPolicy/Attrs", | ||
attrs: generateAttrs(), | ||
policy: longPolicy, | ||
}, | ||
} | ||
var err error | ||
for i := range testCases { | ||
testCases[i].pk, testCases[i].msk, err = Setup(rand.Reader) | ||
if err != nil { | ||
panic(err) | ||
} | ||
} | ||
} | ||
|
||
func BenchmarkTKN20KeyGen(b *testing.B) { | ||
for _, tc := range testCases { | ||
b.Run(fmt.Sprintf("keygen:%s", tc.desc), func(b *testing.B) { | ||
b.ResetTimer() | ||
for i := 0; i < b.N; i++ { | ||
_, err := tc.msk.KeyGen(rand.Reader, tc.attrs) | ||
if err != nil { | ||
b.Fatal(err) | ||
} | ||
} | ||
}) | ||
} | ||
} | ||
|
||
func BenchmarkRSAKeyGen(b *testing.B) { | ||
for i := 0; i < b.N; i++ { | ||
_, err := rsa.GenerateKey(rand.Reader, 2048) | ||
if err != nil { | ||
b.Fatal(err) | ||
} | ||
} | ||
} | ||
|
||
func BenchmarkX25519KeyGen(b *testing.B) { | ||
for i := 0; i < b.N; i++ { | ||
_, _, err := box.GenerateKey(rand.Reader) | ||
if err != nil { | ||
b.Fatal(err) | ||
} | ||
} | ||
} | ||
|
||
func BenchmarkTKN20Encrypt(b *testing.B) { | ||
for _, tc := range testCases { | ||
b.Run(fmt.Sprintf("encrypt:%s", tc.desc), func(b *testing.B) { | ||
b.ResetTimer() | ||
for i := 0; i < b.N; i++ { | ||
_, err := tc.pk.Encrypt(rand.Reader, tc.policy, msg) | ||
if err != nil { | ||
b.Fatal(err) | ||
} | ||
} | ||
}) | ||
} | ||
} | ||
|
||
func BenchmarkRSAEncrypt(b *testing.B) { | ||
privKey, err := rsa.GenerateKey(rand.Reader, 2048) | ||
if err != nil { | ||
b.Fatal(err) | ||
} | ||
pubKey := privKey.PublicKey | ||
b.ResetTimer() | ||
for i := 0; i < b.N; i++ { | ||
_, err := rsa.EncryptPKCS1v15(rand.Reader, &pubKey, msg) | ||
if err != nil { | ||
b.Fatal(err) | ||
} | ||
} | ||
} | ||
|
||
func BenchmarkX25519Encrypt(b *testing.B) { | ||
pubKey, _, err := box.GenerateKey(rand.Reader) | ||
if err != nil { | ||
b.Fatal(err) | ||
} | ||
b.ResetTimer() | ||
for i := 0; i < b.N; i++ { | ||
_, err := box.SealAnonymous(nil, msg, pubKey, rand.Reader) | ||
if err != nil { | ||
b.Fatal(err) | ||
} | ||
} | ||
} | ||
|
||
func BenchmarkTKN20Decrypt(b *testing.B) { | ||
for _, tc := range testCases { | ||
b.Run(fmt.Sprintf("decrypt:%s", tc.desc), func(b *testing.B) { | ||
userKey, err := tc.msk.KeyGen(rand.Reader, tc.attrs) | ||
if err != nil { | ||
b.Fatal(err) | ||
} | ||
ciphertext, err := tc.pk.Encrypt(rand.Reader, tc.policy, msg) | ||
if err != nil { | ||
b.Fatal(err) | ||
} | ||
keyBytes, _ := userKey.MarshalBinary() | ||
pubKeyBytes, _ := tc.pk.MarshalBinary() | ||
// longCt is only benchmarked to measure size overhead | ||
longCt, err := tc.pk.Encrypt(rand.Reader, tc.policy, longMsg) | ||
if err != nil { | ||
b.Fatal(err) | ||
} | ||
b.ResetTimer() | ||
for i := 0; i < b.N; i++ { | ||
_, err = userKey.Decrypt(ciphertext) | ||
if err != nil { | ||
b.Fatal(err) | ||
} | ||
} | ||
b.ReportMetric(float64(len(pubKeyBytes)), "public_key_size") | ||
b.ReportMetric(float64(len(keyBytes)), "attribute_secret_key_size") | ||
b.ReportMetric(float64(len(ciphertext)-len(msg)), "ciphertext_bytes_overhead_32b_msg") | ||
b.ReportMetric(float64(len(longCt)-len(longMsg)), "ciphertext_bytes_overhead_10kb_msg") | ||
}) | ||
} | ||
} | ||
|
||
func BenchmarkRSADecrypt(b *testing.B) { | ||
privKey, err := rsa.GenerateKey(rand.Reader, 2048) | ||
if err != nil { | ||
b.Fatal(err) | ||
} | ||
pubKey := privKey.PublicKey | ||
ct, err := rsa.EncryptPKCS1v15(rand.Reader, &pubKey, msg) | ||
if err != nil { | ||
b.Fatal(err) | ||
} | ||
// longCt is only benchmarked to measure size overhead | ||
longCt, err := rsaEncrypt(longMsg, &privKey.PublicKey) | ||
if err != nil { | ||
b.Fatal(err) | ||
} | ||
b.ResetTimer() | ||
for i := 0; i < b.N; i++ { | ||
_, err := rsa.DecryptPKCS1v15(rand.Reader, privKey, ct) | ||
if err != nil { | ||
b.Fatal(err) | ||
} | ||
} | ||
b.ReportMetric(float64(privKey.PublicKey.Size()), "public_key_size") | ||
b.ReportMetric(float64(len(x509.MarshalPKCS1PrivateKey(privKey))), "secret_key_size") | ||
b.ReportMetric(float64(len(ct)-len(msg)), "ciphertext_bytes_overhead") | ||
b.ReportMetric(float64(len(longCt)-len(longMsg)), "ciphertext_bytes_overhead_10kb_msg") | ||
} | ||
|
||
func BenchmarkX25519Decrypt(b *testing.B) { | ||
pubKey, privKey, err := box.GenerateKey(rand.Reader) | ||
if err != nil { | ||
b.Fatal(err) | ||
} | ||
ct, err := box.SealAnonymous(nil, msg, pubKey, rand.Reader) | ||
if err != nil { | ||
b.Fatal(err) | ||
} | ||
// longCt is only benchmarked to measure size overhead | ||
longCt, err := box.SealAnonymous(nil, longMsg, pubKey, rand.Reader) | ||
if err != nil { | ||
b.Fatal(err) | ||
} | ||
b.ResetTimer() | ||
for i := 0; i < b.N; i++ { | ||
_, ok := box.OpenAnonymous(nil, ct, pubKey, privKey) | ||
if !ok { | ||
b.Fatal(err) | ||
} | ||
} | ||
b.ReportMetric(float64(len(pubKey)), "public_key_size") | ||
b.ReportMetric(float64(len(privKey)), "secret_key_size") | ||
b.ReportMetric(float64(len(ct)-len(msg)), "ciphertext_bytes_overhead_32b_msg") | ||
b.ReportMetric(float64(len(longCt)-len(longMsg)), "ciphertext_bytes_overhead_10kb_msg") | ||
} | ||
|
||
func rsaEncrypt(data []byte, pubKey *rsa.PublicKey) ([]byte, error) { | ||
chunkSize := 245 // Max chunk size for 2048 bit key with PKCS1v15 padding | ||
var ct []byte | ||
for len(data) > 0 { | ||
if len(data) < chunkSize { | ||
chunkSize = len(data) | ||
} | ||
chunk := data[:chunkSize] | ||
data = data[chunkSize:] | ||
encryptedChunk, err := rsa.EncryptPKCS1v15(rand.Reader, pubKey, chunk) | ||
if err != nil { | ||
return nil, err | ||
} | ||
ct = append(ct, encryptedChunk...) | ||
} | ||
return ct, nil | ||
} |