Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Security: why do you require submitting private keys for the aggregatesignature function? #5

Open
Jovonni opened this issue Feb 19, 2024 · 0 comments

Comments

@Jovonni
Copy link

Jovonni commented Feb 19, 2024

The scheme should make use of aggregating public keys, not using private keys, as one of the two parties having access to the other private keys is a security risk

I've tried to do the following

func AggregatePublicKeys(publicKeys [][]byte) ([33]byte, error) {
	var aggregatePubKeyX, aggregatePubKeyY *big.Int

	for _, pubKeyBytes := range publicKeys {
		pubKeyX, pubKeyY := Unmarshal(Curve, pubKeyBytes)
		if pubKeyX == nil || pubKeyY == nil {
			return [33]byte{}, errors.New("invalid public key")
		}
		if aggregatePubKeyX == nil || aggregatePubKeyY == nil {
			aggregatePubKeyX, aggregatePubKeyY = pubKeyX, pubKeyY
		} else {
			// Add the current public key to the aggregate public key.
			aggregatePubKeyX, aggregatePubKeyY = Curve.Add(aggregatePubKeyX, aggregatePubKeyY, pubKeyX, pubKeyY)
		}
	}

	if aggregatePubKeyX == nil || aggregatePubKeyY == nil {
		return [33]byte{}, errors.New("no public keys provided")
	}

	aggregatedPubKeyBytes := Marshal(Curve, aggregatePubKeyX, aggregatePubKeyY)
	var aggregatedPubKey [33]byte
	copy(aggregatedPubKey[:], aggregatedPubKeyBytes)
	return aggregatedPubKey, nil
}

and this test passes:

func TestAggregatePublicKeys(t *testing.T) {
	privKeyHex1 := "B7E151628AED2A6ABF7158809CF4F3C762E7160F38B4DA56A784D9045190CFEF"
	privKeyHex2 := "C90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B14E5C7"

	privKey1, _ := new(big.Int).SetString(privKeyHex1, 16)
	privKey2, _ := new(big.Int).SetString(privKeyHex2, 16)

	pubKey1X, pubKey1Y := Curve.ScalarBaseMult(privKey1.Bytes())
	pubKey2X, pubKey2Y := Curve.ScalarBaseMult(privKey2.Bytes())

	pubKeyBytes1 := Marshal(Curve, pubKey1X, pubKey1Y)
	pubKeyBytes2 := Marshal(Curve, pubKey2X, pubKey2Y)

	aggregatedPubKey, err := AggregatePublicKeys([][]byte{pubKeyBytes1, pubKeyBytes2})
	if err != nil {
		t.Fatalf("Failed to aggregate public keys: %v", err)
	}

	expectedAggregatedPubKeyHex := "03f0a6305d39a34582ba49a78bdf38ced935b3efce1e889d6820103665f35ee45b"
	expectedAggregatedPubKeyBytes, err := hex.DecodeString(expectedAggregatedPubKeyHex)
	if err != nil {
		t.Fatalf("Failed to decode expected aggregated public key hex: %v", err)
	}

	aggregatedPubKeyHex := hex.EncodeToString(aggregatedPubKey[:])

	if aggregatedPubKeyHex != expectedAggregatedPubKeyHex {
		t.Errorf("Aggregated public key does not match the expected value.\nExpected: %s\nGot: %s", expectedAggregatedPubKeyHex, aggregatedPubKeyHex)
	}

	if hex.EncodeToString(expectedAggregatedPubKeyBytes) != aggregatedPubKeyHex {
		t.Errorf("Aggregated public key bytes do not match the expected bytes.\nExpected: %x\nGot: %x", expectedAggregatedPubKeyBytes, aggregatedPubKey)
	}
}

but this test fails

func TestVerifyWithAggregatedPublicKey(t *testing.T) {
	// Step 1: Aggregate public keys
	privKeysHex := []string{
		"B7E151628AED2A6ABF7158809CF4F3C762E7160F38B4DA56A784D9045190CFEF",
		"C90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B14E5C7",
	}
	var publicKeys [][]byte
	for _, hexKey := range privKeysHex {
		privKey, ok := new(big.Int).SetString(hexKey, 16)
		if !ok {
			t.Fatalf("Failed to parse private key: %s", hexKey)
		}
		px, py := Curve.ScalarBaseMult(privKey.Bytes())
		publicKeys = append(publicKeys, Marshal(Curve, px, py))
	}
	fmt.Println(publicKeys)
	aggregatedPublicKey, err := AggregatePublicKeys(publicKeys)
	if err != nil {
		t.Fatalf("Failed to aggregate public keys: %v", err)
	}

	// Step 2: Sign a message using one of the private keys 
	message := [32]byte{ /* your message here, can be random */ }
	privKeyBigInt, ok := new(big.Int).SetString(privKeysHex[0], 16)
	if !ok {
		t.Fatalf("Failed to parse private key: %s", privKeysHex[0])
	}
	signature, err := Sign(privKeyBigInt, message)
	if err != nil {
		t.Fatalf("Failed to sign message: %v", err)
	}

	// Step 3: Verify the signature against the aggregated public key
	verified, err := Verify(aggregatedPublicKey, message, signature)
	if err != nil {
		t.Fatalf("Verification failed with error: %v", err)
	}
	if !verified {
		t.Fatal("Failed to verify signature with aggregated public key")
	}
}

why does the AggregateSignatures function signature expect a set of private keys instead of public keys:

func AggregateSignatures(privateKeys []*big.Int, message [32]byte) ([64]byte, error) {
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant