Skip to content

Commit 7ac9899

Browse files
authored
Merge pull request #301 from /issues/300
Fixed 65bit public key issue
2 parents 3223936 + 8726ebc commit 7ac9899

2 files changed

Lines changed: 94 additions & 3 deletions

File tree

src/main/java/com/syntifi/crypto/key/Secp256k1PublicKey.java

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.syntifi.crypto.key;
22

3+
import com.casper.sdk.model.key.AlgorithmTag;
34
import com.syntifi.crypto.key.encdec.Hex;
45
import lombok.EqualsAndHashCode;
56
import lombok.NoArgsConstructor;
@@ -77,7 +78,7 @@ public void writePublicKey(final Writer writer) throws IOException {
7778
public Boolean verify(byte[] message, byte[] signature) {
7879

7980
//We need the Public key's short key
80-
byte[] keyToFind = (getKey().length > 33) ? getShortKey(getKey()) : getKey();
81+
byte[] keyToFind = (getKey().length > AlgorithmTag.SECP256K1.getLength()) ? getShortKey(getKey()) : getKey();
8182

8283
//Looping possible v's of the signature
8384
for (int i = 27; i <= 34; i++) {
@@ -97,7 +98,7 @@ public Boolean verify(byte[] message, byte[] signature) {
9798

9899
if (recoveredKey != null) {
99100

100-
final byte[] keyFromSignature = getShortKey(recoveredKey.toByteArray());
101+
final byte[] keyFromSignature = getRecoveredShortKey(recoveredKey.toByteArray());
101102

102103
if (Arrays.equals(keyFromSignature, keyToFind)) {
103104
return true;
@@ -120,7 +121,25 @@ public Boolean verify(byte[] message, byte[] signature) {
120121
public static byte[] getShortKey(final byte[] key) {
121122
final BigInteger pubKey = new BigInteger(key);
122123
final String pubKeyPrefix = pubKey.testBit(0) ? "03" : "02";
123-
final byte[] pubKeyBytes = Arrays.copyOfRange(key, 0, 32);
124+
final byte[] pubKeyBytes = Arrays.copyOfRange(key, 0, (AlgorithmTag.SECP256K1.getLength() - 1));
124125
return Hex.decode(pubKeyPrefix + Hex.encode(pubKeyBytes));
125126
}
127+
128+
/**
129+
* There's around a 50% chance the elliptical curve algo will generate a 65 byte
130+
* public key instead of 66 byte.
131+
* Luckily the algo pads the first byte as zero when this happens
132+
* Determine this and then return the byte array to be shortened
133+
*
134+
* @param key the key as a byte array
135+
* @return short key as byte array
136+
*/
137+
public static byte[] getRecoveredShortKey(final byte[] key){
138+
if (key[0] == (byte) 0) {
139+
return getShortKey(Arrays.copyOfRange(key, 1, (key.length - 1)));
140+
} else {
141+
return getShortKey(key);
142+
}
143+
}
144+
126145
}

src/test/java/com/syntifi/crypto/key/Secp256k1PublicKeyTests.java

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.syntifi.crypto.key;
22

3+
import com.casper.sdk.model.key.PublicKey;
34
import com.syntifi.crypto.key.encdec.Hex;
45
import org.junit.jupiter.api.Test;
56
import org.slf4j.Logger;
@@ -8,6 +9,7 @@
89
import java.io.File;
910
import java.io.IOException;
1011
import java.net.URISyntaxException;
12+
import java.security.GeneralSecurityException;
1113
import java.text.DateFormat;
1214
import java.text.SimpleDateFormat;
1315
import java.util.Date;
@@ -146,4 +148,74 @@ void signAndRecoverPublicKey_4() throws URISyntaxException, IOException {
146148

147149
}
148150

151+
@Test
152+
void signAndRecoverPublicKey_5() throws GeneralSecurityException {
153+
154+
String publicKey = "02027fec2d969dd0779358c40abe2a772f309408348c2a1f413fddfe684a4287ba1a";
155+
String signature = "2f26d3a896e5ad74bafc381455fc9bec808cea64b083b4a05e3dae43d80478820f59128c97bb50b52d5eba90eb29ec8dbd1b39fe6488bbc8c44a799e9a631878";
156+
String hash = "92c983f3bb205b4f642f532dff837ebed56b19f11351da9181f6512e75a54a9b";
157+
158+
PublicKey key = new PublicKey();
159+
key.createPublicKey(publicKey);
160+
161+
assert key.getPubKey().verify(Hex.decode(hash), Hex.decode(signature));
162+
163+
}
164+
165+
@Test
166+
void signAndRecoverPublicKey_6() throws GeneralSecurityException {
167+
168+
String publicKey = "02024c5e3ba7b1da49cda950319aec914cd3c720fbec3dcf25aa4add631e28f70aa9";
169+
String signature = "ade1d9902ec5520e0f52052b329cc62620ac5e84294729c559ce979fe0cf22aa29a8cef7a9d985851da01f68b4049ad9db3d310440cafcb3b5fe40ed6040aa1e";
170+
String hash = "57a2fc930ab83f6bf5b3f1d7d5d1bd05ccd20dcbe3135f7c21a0553650d220e6";
171+
172+
PublicKey key = new PublicKey();
173+
key.createPublicKey(publicKey);
174+
175+
assert key.getPubKey().verify(Hex.decode(hash), Hex.decode(signature));
176+
177+
}
178+
179+
@Test
180+
void signAndRecoverPublicKey_7() throws GeneralSecurityException {
181+
182+
String publicKey = "0203b34ffdb855f8654f7f3805257844fe08d4055bcf75bbbb19b78463e34ba8b932";
183+
String signature = "29d7ea92f1193c13c7ab5d90dfdfab75f52fd49047b9bb4fafc9962a7a1e0d2a36828d93d0d95080f53c625a2f2111dd86c37391f9a05a7ea5a1f2abba579476";
184+
String hash = "3fa94f85c55a44a8afc2944914eb38720cc85d4b130809f8409a8c7e3e677298";
185+
186+
PublicKey key = new PublicKey();
187+
key.createPublicKey(publicKey);
188+
189+
assert key.getPubKey().verify(Hex.decode(hash), Hex.decode(signature));
190+
191+
}
192+
193+
@Test
194+
void signAndRecoverPublicKey_8() throws GeneralSecurityException {
195+
196+
String publicKey = "020287a38f11ac7aab689205912b981c21b80cf1efdd7541bd09cbe1e6ad6e8f188c";
197+
String signature = "d1a796f1221e2256dbe85904e2c3d07be52c1482f8b3cfdce0bef0b6d4c5fc5537e3d8720054888eba9ddcb4c6ff388fabb5c09143000980e6af9096ee163524";
198+
String hash = "1df13c9aaa8217657b7e5ec2442594735eeb4ca7e764877b3d2b593c3909d15f";
199+
200+
PublicKey key = new PublicKey();
201+
key.createPublicKey(publicKey);
202+
203+
assert key.getPubKey().verify(Hex.decode(hash), Hex.decode(signature));
204+
205+
}
206+
207+
@Test
208+
void signAndRecoverPublicKey_9() throws GeneralSecurityException {
209+
String publicKey = "0202ea6c7f7f281078af87e79a3856d500da39d35743d8253c9bc1fce7b1da0a3536";
210+
String signature = "c808c81f8db9a3a7364b0d884968c74427ace3fbd66cef9a8f0235e570b2774407071b63094446992e37c8f0e7d154bacd882d583fa2bfb043c884e445da56aa";
211+
String hash = "e96cb427900710e89e39f3a69b8f576c8b5cb3085702f3c33c46fcbb115f1775";
212+
213+
PublicKey key = new PublicKey();
214+
key.createPublicKey(publicKey);
215+
216+
assert key.getPubKey().verify(Hex.decode(hash), Hex.decode(signature));
217+
218+
}
219+
220+
149221
}

0 commit comments

Comments
 (0)