Skip to content

Commit

Permalink
Merge pull request #255 from /issues/219
Browse files Browse the repository at this point in the history
issues/219 - Fix for PublicKey byte deserialization.
  • Loading branch information
cnorburn authored Mar 13, 2024
2 parents c31faa7 + dce2cbe commit 8ffe176
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
import dev.oak3.sbs4j.DeserializerBuffer;
import dev.oak3.sbs4j.SerializerBuffer;
import dev.oak3.sbs4j.exception.ValueSerializationException;
import dev.oak3.sbs4j.util.ByteUtils;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NoArgsConstructor;
Expand Down Expand Up @@ -54,7 +53,7 @@ protected void serializeValue(final SerializerBuffer ser) throws ValueSerializat

@Override
public void deserializeCustom(final DeserializerBuffer deser) throws Exception {
this.setValue(PublicKey.fromTaggedHexString(ByteUtils.encodeHexString(deser.readByteArray(33))));
this.setValue(PublicKey.deserialize(deser));
}

@Override
Expand Down
5 changes: 4 additions & 1 deletion src/main/java/com/casper/sdk/model/key/AlgorithmTag.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,11 @@
@Getter
@AllArgsConstructor(access = AccessLevel.PRIVATE)
public enum AlgorithmTag implements Tag {
SECP256K1((byte) 0x02), ED25519((byte) 0x01);
SECP256K1((byte) 0x02, 33), ED25519((byte) 0x01, 32);

private final byte byteTag;
/** The number of bytes for a key excluding the tag byte */
private final int length;

public static AlgorithmTag getByTag(byte byteTag) throws NoSuchAlgorithmException {
for (AlgorithmTag a : values()) {
Expand All @@ -29,4 +31,5 @@ public static AlgorithmTag getByTag(byte byteTag) throws NoSuchAlgorithmExceptio
}
throw new NoSuchAlgorithmException();
}

}
40 changes: 25 additions & 15 deletions src/main/java/com/casper/sdk/model/key/PublicKey.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,14 @@
import com.syntifi.crypto.key.Ed25519PublicKey;
import com.syntifi.crypto.key.Secp256k1PublicKey;
import com.syntifi.crypto.key.hash.Blake2b;
import dev.oak3.sbs4j.DeserializerBuffer;
import dev.oak3.sbs4j.exception.ValueDeserializationException;
import dev.oak3.sbs4j.util.ByteUtils;
import lombok.NoArgsConstructor;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;

Expand All @@ -29,39 +32,46 @@ public class PublicKey extends AbstractSerializedKeyTaggedHex<AlgorithmTag> {

public static PublicKey fromTaggedHexString(String hex)
throws NoSuchAlgorithmException, IllegalArgumentException {
byte[] bytes = ByteUtils.parseHexString(hex);
return PublicKey.fromBytes(bytes);
return PublicKey.fromBytes(ByteUtils.parseHexString(hex));
}

public static PublicKey fromBytes(byte[] bytes) throws NoSuchAlgorithmException {
PublicKey object = new PublicKey();
public static PublicKey fromBytes(final byte[] bytes) throws NoSuchAlgorithmException {
final PublicKey object = new PublicKey();
object.setTag(AlgorithmTag.getByTag(bytes[0]));
object.setKey(Arrays.copyOfRange(bytes, 1, bytes.length));

return object;
}

public static PublicKey fromAbstractPublicKey(AbstractPublicKey key) {
PublicKey object = new PublicKey();
object.setTag((key instanceof Secp256k1PublicKey)
? AlgorithmTag.SECP256K1
: AlgorithmTag.ED25519);
public static PublicKey fromAbstractPublicKey(final AbstractPublicKey key) {
final PublicKey object = new PublicKey();
object.setTag((key instanceof Secp256k1PublicKey) ? AlgorithmTag.SECP256K1 : AlgorithmTag.ED25519);
object.setKey(key.getKey());
return object;
}

public String generateAccountHash(boolean includePrefix) throws IOException {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
byteArrayOutputStream.write(getTag().toString().toLowerCase().getBytes("UTF-8"));
public static PublicKey deserialize(final DeserializerBuffer deser) throws ValueDeserializationException, NoSuchAlgorithmException {
// Obtain algorithm tag
final AlgorithmTag tag = AlgorithmTag.getByTag(deser.readU8());
final PublicKey publicKey = new PublicKey();
publicKey.setTag(tag);
// Read the required number of bytes for the algorithm length
publicKey.setKey(deser.readByteArray(tag.getLength()));
return publicKey;
}


public String generateAccountHash(final boolean includePrefix) throws IOException {
final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
byteArrayOutputStream.write(getTag().toString().toLowerCase().getBytes(StandardCharsets.UTF_8));
byteArrayOutputStream.write(0);
byteArrayOutputStream.write(getKey());

return (includePrefix ? "account-hash-" : "") + ByteUtils.encodeHexString(Blake2b.digest(byteArrayOutputStream.toByteArray(), 32));
}

@JsonCreator
public void createPublicKey(String key) throws NoSuchAlgorithmException, IllegalArgumentException {
PublicKey obj = PublicKey.fromTaggedHexString(key);
public void createPublicKey(final String key) throws NoSuchAlgorithmException, IllegalArgumentException {
final PublicKey obj = PublicKey.fromTaggedHexString(key);
this.setTag(obj.getTag());
this.setKey(obj.getKey());
}
Expand Down
41 changes: 41 additions & 0 deletions src/test/java/com/casper/sdk/model/clvalue/CLValueTests.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,14 @@

import com.casper.sdk.exception.DynamicInstanceException;
import com.casper.sdk.exception.NoSuchTypeException;
import com.casper.sdk.helper.CasperKeyHelper;
import com.casper.sdk.model.clvalue.cltype.*;
import com.casper.sdk.model.clvalue.serde.Target;
import com.casper.sdk.model.deploy.NamedArg;
import com.casper.sdk.model.key.PublicKey;
import com.syntifi.crypto.key.AbstractPublicKey;
import com.syntifi.crypto.key.Ed25519PrivateKey;
import com.syntifi.crypto.key.Secp256k1PrivateKey;
import com.syntifi.crypto.key.encdec.Hex;
import dev.oak3.sbs4j.DeserializerBuffer;
import dev.oak3.sbs4j.SerializerBuffer;
Expand Down Expand Up @@ -323,4 +328,40 @@ void nestedListSerialization() throws Exception {

assertThat(clValueList.getBytes(), is(outerList.getBytes()));
}

@Test
void secp256k1PublicKeySerialization() throws Exception {

final Secp256k1PrivateKey secp256k1PrivateKey = CasperKeyHelper.createRandomSecp256k1Key();
final AbstractPublicKey abstractPublicKey = secp256k1PrivateKey.derivePublicKey();
final PublicKey publicKey = PublicKey.fromAbstractPublicKey(abstractPublicKey);

final CLValuePublicKey clValuePublicKey = new CLValuePublicKey(publicKey);
final SerializerBuffer ser = new SerializerBuffer();
clValuePublicKey.serialize(ser, Target.BYTE);

final byte[] bytes = ser.toByteArray();
assertThat(bytes.length, is(39));

final CLValuePublicKey deserialized = (CLValuePublicKey) clValuePublicKey.deserialize(new DeserializerBuffer(bytes), Target.BYTE);
assertThat(deserialized.getBytes(), is(clValuePublicKey.getBytes()));
}

@Test
void Ed25519PublicKeySerialization() throws Exception {
Ed25519PrivateKey randomEd25519Key = CasperKeyHelper.createRandomEd25519Key();
final AbstractPublicKey abstractPublicKey = randomEd25519Key.derivePublicKey();
final PublicKey publicKey = PublicKey.fromAbstractPublicKey(abstractPublicKey);

final CLValuePublicKey clValuePublicKey = new CLValuePublicKey(publicKey);
final SerializerBuffer ser = new SerializerBuffer();
clValuePublicKey.serialize(ser, Target.BYTE);

final byte[] bytes = ser.toByteArray();
assertThat(bytes.length, is(38));

final CLValuePublicKey deserialized = (CLValuePublicKey) clValuePublicKey.deserialize(new DeserializerBuffer(bytes), Target.BYTE);
assertThat(deserialized.getBytes(), is(clValuePublicKey.getBytes()));
}

}

0 comments on commit 8ffe176

Please sign in to comment.