Skip to content

Commit 6a6494f

Browse files
authored
feat: bls public key validation (#190)
1 parent c278921 commit 6a6494f

5 files changed

Lines changed: 164 additions & 0 deletions

File tree

build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ dependencies {
2727
implementation 'org.bouncycastle:bcprov-jdk15on:1.70'
2828
implementation 'org.web3j:core:4.8.7'
2929
implementation 'com.google.code.gson:gson:2.11.0'
30+
implementation 'foundation.icon:blst-java:0.3.2'
3031

3132
// Test dependencies
3233
testImplementation 'org.hamcrest:hamcrest-library:3.0'
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package org.arkecosystem.crypto.identities;
2+
3+
import org.arkecosystem.crypto.encoding.Hex;
4+
import supranational.blst.P1_Affine;
5+
6+
public class BlsPublicKey {
7+
8+
public static boolean validate(String publicKeyHex) {
9+
try {
10+
if (publicKeyHex == null) {
11+
return false;
12+
}
13+
14+
if (publicKeyHex.startsWith("0x")) {
15+
publicKeyHex = publicKeyHex.substring(2);
16+
}
17+
18+
if (publicKeyHex.length() != 96) {
19+
return false;
20+
}
21+
22+
byte[] publicKeyBytes = Hex.decode(publicKeyHex);
23+
24+
P1_Affine point = new P1_Affine(publicKeyBytes);
25+
26+
return point.in_group();
27+
} catch (Exception e) {
28+
return false;
29+
}
30+
}
31+
}

src/main/java/org/arkecosystem/crypto/transactions/builder/ValidatorRegistrationBuilder.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,16 @@
11
package org.arkecosystem.crypto.transactions.builder;
22

3+
import org.arkecosystem.crypto.identities.BlsPublicKey;
34
import org.arkecosystem.crypto.transactions.types.AbstractTransaction;
45
import org.arkecosystem.crypto.transactions.types.ValidatorRegistration;
56

67
public class ValidatorRegistrationBuilder
78
extends AbstractTransactionBuilder<ValidatorRegistrationBuilder> {
89
public ValidatorRegistrationBuilder validatorPublicKey(String validatorPublicKey) {
10+
if (!BlsPublicKey.validate(validatorPublicKey)) {
11+
throw new IllegalArgumentException("Invalid BLS public key");
12+
}
13+
914
this.transaction.validatorPublicKey = validatorPublicKey;
1015

1116
this.transaction.refreshPayloadData();
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
package org.arkecosystem.crypto.identities;
2+
3+
import static org.junit.jupiter.api.Assertions.assertFalse;
4+
import static org.junit.jupiter.api.Assertions.assertTrue;
5+
6+
import org.junit.jupiter.api.Test;
7+
8+
public class BlsPublicKeyTest {
9+
10+
@Test
11+
public void validBlsPublicKeyFromMnemonic() {
12+
assertTrue(
13+
BlsPublicKey.validate(
14+
"b4865127896c3c5286296a7b26e7c8002586a3ecf5832bfb59e689336f1f4c75e10491b9dfaed8dfb2c2fbe22d11fa93"));
15+
}
16+
17+
@Test
18+
public void validG1GeneratorPoint() {
19+
assertTrue(
20+
BlsPublicKey.validate(
21+
"97f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb"));
22+
}
23+
24+
@Test
25+
public void validSecondBlsPublicKey() {
26+
assertTrue(
27+
BlsPublicKey.validate(
28+
"95af988701a6fb60e09da41d2ca1a9e0b49e43501bda4255b3ca01073f490c34102b6bbcafde6333185e9980745d72cb"));
29+
}
30+
31+
@Test
32+
public void validBlsPublicKeyWith0xPrefix() {
33+
assertTrue(
34+
BlsPublicKey.validate(
35+
"0xb4865127896c3c5286296a7b26e7c8002586a3ecf5832bfb59e689336f1f4c75e10491b9dfaed8dfb2c2fbe22d11fa93"));
36+
}
37+
38+
@Test
39+
public void emptyString() {
40+
assertFalse(BlsPublicKey.validate(""));
41+
}
42+
43+
@Test
44+
public void singleCharacter() {
45+
assertFalse(BlsPublicKey.validate("0"));
46+
}
47+
48+
@Test
49+
public void nonHexString() {
50+
assertFalse(BlsPublicKey.validate("NOT A VALID PUBLICKEY"));
51+
}
52+
53+
@Test
54+
public void invalidHexCharactersMixedWithValid() {
55+
assertFalse(BlsPublicKey.validate("02b5Gf"));
56+
}
57+
58+
@Test
59+
public void tooShort33BytesZeroPadded() {
60+
assertFalse(
61+
BlsPublicKey.validate(
62+
"000000000000000000000000000000000000000000000000000000000000000000"));
63+
}
64+
65+
@Test
66+
public void secp256k1CompressedPublicKeyPrefix02() {
67+
assertFalse(
68+
BlsPublicKey.validate(
69+
"02e0f7449c5588f24492c338f2bc8f7865f755b958d48edb0f2d0056e50c3fd5b7"));
70+
}
71+
72+
@Test
73+
public void secp256k1CompressedPublicKeyPrefix03() {
74+
assertFalse(
75+
BlsPublicKey.validate(
76+
"038c14b793cb19137e323a6d2e2a870bca2e7a493ec1153b3a95feb8a4873f8d08"));
77+
}
78+
79+
@Test
80+
public void secp256k1CompressedKeyWithInvalidHex() {
81+
assertFalse(
82+
BlsPublicKey.validate(
83+
"02b5Gf00d9de5a3ace28913fe78a15afcfe242926e94d9b517d06d2705b261f992"));
84+
}
85+
86+
@Test
87+
public void secp256k1UncompressedLengthKeyPrefix32() {
88+
assertFalse(
89+
BlsPublicKey.validate(
90+
"32337416a26d8d49ec27059bd0589c49bb474029c3627715380f4df83fb431aece"));
91+
}
92+
93+
@Test
94+
public void secp256k1UncompressedLengthKeyPrefix22() {
95+
assertFalse(
96+
BlsPublicKey.validate(
97+
"22337416a26d8d49ec27059bd0589c49bb474029c3627715380f4df83fb431aece"));
98+
}
99+
100+
@Test
101+
public void correctLengthButInvalidPoint() {
102+
assertFalse(
103+
BlsPublicKey.validate(
104+
"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001"));
105+
}
106+
107+
@Test
108+
public void tooLongBy1Byte() {
109+
assertFalse(
110+
BlsPublicKey.validate(
111+
"b4865127896c3c5286296a7b26e7c8002586a3ecf5832bfb59e689336f1f4c75e10491b9dfaed8dfb2c2fbe22d11fa9300"));
112+
}
113+
114+
@Test
115+
public void nullInput() {
116+
assertFalse(BlsPublicKey.validate(null));
117+
}
118+
}

src/test/java/org/arkecosystem/crypto/transactions/builder/ValidatorRegistrationBuilderTest.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,4 +33,13 @@ public void it_should_sign_it_with_a_passphrase() throws Exception {
3333
assertEquals(data.get("id"), builder.transaction.getId());
3434
assertTrue(builder.verify());
3535
}
36+
37+
@Test
38+
public void it_should_throw_on_invalid_bls_public_key() {
39+
assertThrows(
40+
IllegalArgumentException.class,
41+
() -> {
42+
new ValidatorRegistrationBuilder().validatorPublicKey("invalid-bls-key");
43+
});
44+
}
3645
}

0 commit comments

Comments
 (0)