Skip to content

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

@Jovonni

Description

@Jovonni

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) {

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions