Skip to content

Commit

Permalink
chore: Cleanup Signature (#15570)
Browse files Browse the repository at this point in the history
Signed-off-by: Timo Brandstätter <[email protected]>
  • Loading branch information
timo0 authored Oct 4, 2024
1 parent e898393 commit 273d6e8
Show file tree
Hide file tree
Showing 14 changed files with 116 additions and 94 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ static void writeSignatureFile(
* @return Signature object
*/
private static SignatureObject generateSignatureObject(@NonNull final Signer signer, @NonNull final Bytes hash) {
final Bytes signature = Bytes.wrap(signer.sign(hash.toByteArray()).getSignatureBytes());
final Bytes signature = signer.sign(hash.toByteArray()).getBytes();
return SignatureObject.newBuilder()
.type(SignatureType.SHA_384_WITH_RSA)
.length((int) signature.length())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

import static com.swirlds.logging.legacy.LogMarker.EXCEPTION;

import com.hedera.pbj.runtime.io.buffer.Bytes;
import com.swirlds.common.crypto.Signature;
import com.swirlds.common.merkle.MerkleNode;
import com.swirlds.common.platform.NodeId;
Expand Down Expand Up @@ -214,7 +215,7 @@ public void signAccountBalanceFile(final Platform platform, final String balance
byte[] fileHash = getFileHash(balanceFileName);
Signature signature = platform.sign(fileHash);

String sigFileName = generateSigFile(balanceFileName, signature.getSignatureBytes(), fileHash);
final String sigFileName = generateSigFile(balanceFileName, signature.getBytes(), fileHash);
if (sigFileName != null) {
if (logger.isDebugEnabled()) {
logger.debug("Generated signature file for {}", balanceFileName);
Expand All @@ -226,11 +227,12 @@ public void signAccountBalanceFile(final Platform platform, final String balance
* Create a signature file for a RecordStream/AccountBalance file;
* This signature file contains the Hash of the file to be signed, and a signature signed by the node's Key
*
* @param fileName
* @param signature
* @param fileHash
* @param fileName the name of the file to be signed
* @param signatureBytes the signature bytes
* @param fileHash the hash of the file to be signed
*/
public static String generateSigFile(String fileName, byte[] signature, byte[] fileHash) {
private static String generateSigFile(final String fileName, final Bytes signatureBytes, byte[] fileHash) {
final byte[] signature = signatureBytes.toByteArray();
try {
String newFileName = fileName + "_sig";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,74 +17,46 @@
package com.swirlds.common.crypto;

import static com.swirlds.common.crypto.SignatureType.RSA;
import static com.swirlds.common.utility.CommonUtils.hex;

import com.hedera.pbj.runtime.io.buffer.Bytes;
import com.swirlds.base.utility.ToStringBuilder;
import com.swirlds.common.io.SelfSerializable;
import com.swirlds.common.io.streams.SerializableDataInputStream;
import com.swirlds.common.io.streams.SerializableDataOutputStream;
import edu.umd.cs.findbugs.annotations.NonNull;
import java.io.IOException;
import java.util.Arrays;
import java.util.Objects;

/**
* Encapsulates a cryptographic signature along with its SignatureType.
*/
public class Signature implements SelfSerializable {
public class Signature {
/** a unique class type identifier */
private static final long CLASS_ID = 0x13dc4b399b245c69L;

/** the current serialization version */
private static final int CLASS_VERSION = 1;

/** The type of cryptographic algorithm used to create the signature */
private SignatureType signatureType;
private final SignatureType signatureType;

/** signature byte array */
private byte[] signatureBytes;
private final Bytes signatureBytes;

/**
* For RuntimeConstructable
*/
public Signature() {}

public Signature(final SignatureType signatureType, final byte[] signatureBytes) {
this.signatureType = signatureType;
this.signatureBytes = signatureBytes;
public Signature(@NonNull final SignatureType signatureType, @NonNull final byte[] signatureBytes) {
this(signatureType, Bytes.wrap(signatureBytes));
}

/**
* {@inheritDoc}
*/
@Override
public void deserialize(final SerializableDataInputStream in, final int version) throws IOException {
this.signatureType = SignatureType.from(in.readInt(), RSA);
this.signatureBytes = in.readByteArray(this.signatureType.signatureLength(), true);
}

/**
* {@inheritDoc}
*/
@Override
public void serialize(final SerializableDataOutputStream out) throws IOException {
out.writeInt(signatureType.ordinal());
out.writeByteArray(signatureBytes, true);
}

/**
* Get the bytes of this signature.
*/
public byte[] getSignatureBytes() {
return signatureBytes;
public Signature(@NonNull final SignatureType signatureType, @NonNull final Bytes signatureBytes) {
this.signatureType = Objects.requireNonNull(signatureType, "signatureType should not be null");
this.signatureBytes = Objects.requireNonNull(signatureBytes, "signatureBytes should not be null");
}

/**
* @return the bytes of this signature in an immutable instance
*/
public @NonNull Bytes getBytes() {
return Bytes.wrap(signatureBytes);
@NonNull
public Bytes getBytes() {
return signatureBytes;
}

/**
Expand All @@ -95,22 +67,6 @@ public SignatureType getType() {
return signatureType;
}

/**
* {@inheritDoc}
*/
@Override
public long getClassId() {
return CLASS_ID;
}

/**
* {@inheritDoc}
*/
@Override
public int getVersion() {
return CLASS_VERSION;
}

/**
* {@inheritDoc}
*/
Expand All @@ -124,15 +80,53 @@ public boolean equals(final Object obj) {
return false;
}

return Arrays.equals(signatureBytes, signature.signatureBytes) && signatureType == signature.signatureType;
return Objects.equals(signatureBytes, signature.signatureBytes) && signatureType == signature.signatureType;
}

/**
* {@inheritDoc}
*/
@Override
public int hashCode() {
return Objects.hash(signatureType, Arrays.hashCode(signatureBytes));
return Objects.hash(signatureType, signatureBytes);
}

/**
* Deserialize a signature from a stream.
*
* @param in the stream to read from
* @param readClassId whether to read the class ID from the stream
*
* @return the signature read from the stream
*/
public static Signature deserialize(final SerializableDataInputStream in, final boolean readClassId)
throws IOException {
if (readClassId) {
final long classId = in.readLong();
if (classId != CLASS_ID) {
throw new IOException("unexpected class ID: " + classId);
}
}
in.readInt(); // ignore version
final SignatureType signatureType = SignatureType.from(in.readInt(), RSA);
final byte[] signatureBytes = in.readByteArray(signatureType.signatureLength(), true);

return new Signature(signatureType, signatureBytes);
}

/**
* Serialize this signature to a stream.
*
* @param out the stream to write to
* @param withClassId whether to write the class ID to the stream
*/
public void serialize(final SerializableDataOutputStream out, final boolean withClassId) throws IOException {
if (withClassId) {
out.writeLong(CLASS_ID);
}
out.writeInt(CLASS_VERSION);
out.writeInt(signatureType.ordinal());
out.writeByteArray(signatureBytes.toByteArray(), true);
}

/**
Expand All @@ -142,7 +136,7 @@ public int hashCode() {
public String toString() {
return new ToStringBuilder(this)
.append("signatureType", signatureType)
.append("sigBytes", hex(signatureBytes))
.append("sigBytes", signatureBytes)
.toString();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -293,13 +293,13 @@ public static Pair<Pair<Hash, Signature>, Pair<Hash, Signature>> parseSigFile(
// read OBJECT_STREAM_SIG_VERSION
inputStream.readInt();
// read entireHash
Hash entireHash = inputStream.readSerializable();
final Hash entireHash = inputStream.readSerializable();
// read entireSignature
Signature entireSignature = inputStream.readSerializable();
final Signature entireSignature = Signature.deserialize(inputStream, true);
// read metaHash
Hash metaHash = inputStream.readSerializable();
final Hash metaHash = inputStream.readSerializable();
// read metaSignature
Signature metaSignature = inputStream.readSerializable();
final Signature metaSignature = Signature.deserialize(inputStream, true);

return Pair.of(Pair.of(entireHash, entireSignature), Pair.of(metaHash, metaSignature));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ public static boolean verifySignature(final Hash hash, final Signature signature
SignatureType.RSA.signingAlgorithm(), SignatureType.RSA.provider());
sig.initVerify(publicKey);
hash.getBytes().updateSignature(sig);
return sig.verify(signature.getSignatureBytes());
return signature.getBytes().verifySignature(sig);
} catch (final NoSuchAlgorithmException
| NoSuchProviderException
| InvalidKeyException
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,12 @@
public class TimestampStreamFileWriter<T extends StreamAligned & RunningHashable & SerializableHashable & Timestamped>
implements LinkedObjectStream<T> {

/** a unique class type identifier */
private static final long SIGNATURE_CLASS_ID = 0x13dc4b399b245c69L;

/** the current serialization version */
private static final int CLASS_VERSION = 1;

/**
* The serialization format of the stream files.
*/
Expand Down Expand Up @@ -216,9 +222,9 @@ public static void writeSignatureFile(

output.writeInt(OBJECT_STREAM_SIG_VERSION);
output.writeSerializable(entireHash, true);
output.writeSerializable(entireSignature, true);
entireSignature.serialize(output, true);
output.writeSerializable(metaHash, true);
output.writeSerializable(metaSignature, true);
metaSignature.serialize(output, true);

logger.info(OBJECT_STREAM_FILE.getMarker(), "signature file saved: {}", sigFilePath);
}
Expand Down Expand Up @@ -339,10 +345,10 @@ public void closeCurrentAndSign() {

// generate signature for entire Hash
final Signature entireSignature = new Signature(
SIGNATURE_TYPE, signer.sign(entireHash.copyToByteArray()).getSignatureBytes());
SIGNATURE_TYPE, signer.sign(entireHash.copyToByteArray()).getBytes());
// generate signature for metaData Hash
final Signature metaSignature = new Signature(
SIGNATURE_TYPE, signer.sign(metaHash.copyToByteArray()).getSignatureBytes());
SIGNATURE_TYPE, signer.sign(metaHash.copyToByteArray()).getBytes());
try {
writeSignatureFile(
entireHash,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@

package com.swirlds.common.crypto;

import static com.swirlds.common.test.fixtures.io.SerializationUtils.serializeDeserialize;
import static org.junit.jupiter.api.Assertions.assertEquals;

import com.swirlds.common.constructable.ConstructableRegistry;
import com.swirlds.common.constructable.ConstructableRegistryException;
import com.swirlds.common.test.fixtures.io.InputOutputStream;
import java.io.IOException;
import java.util.concurrent.ThreadLocalRandom;
import org.junit.jupiter.api.BeforeAll;
Expand All @@ -41,4 +41,12 @@ public void serializeDeserializeTest() throws IOException {
Signature deserialized = serializeDeserialize(signature);
assertEquals(signature, deserialized);
}

private Signature serializeDeserialize(final Signature signature) throws IOException {
try (final InputOutputStream io = new InputOutputStream()) {
signature.serialize(io.getOutput(), true);
io.startReading();
return Signature.deserialize(io.getInput(), true);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -224,8 +224,8 @@ void nextSignatureUnique() {
final Signature signature2 = random2.nextSignature();

assertNotEquals(signature1, signature2);
assertEquals(384, signature1.getSignatureBytes().length);
assertEquals(384, signature2.getSignatureBytes().length);
assertEquals(384, signature1.getBytes().length());
assertEquals(384, signature2.getBytes().length());
}

@Test
Expand All @@ -235,8 +235,8 @@ void nextSignatureSameSeed() {
final Signature signature2 = random1Duplicate.nextSignature();

assertEquals(signature1, signature2);
assertEquals(384, signature1.getSignatureBytes().length);
assertEquals(384, signature2.getSignatureBytes().length);
assertEquals(384, signature1.getBytes().length());
assertEquals(384, signature2.getBytes().length());
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,11 +102,21 @@ public class PlatformEvent implements ConsensusEvent, Hashable {
* @param signature the signature for the event
*/
public PlatformEvent(@NonNull final UnsignedEvent unsignedEvent, @NonNull final byte[] signature) {
this(unsignedEvent, Bytes.wrap(signature));
}

/**
* Construct a new instance from an unsigned event and a signature.
*
* @param unsignedEvent the unsigned event
* @param signature the signature for the event
*/
public PlatformEvent(@NonNull final UnsignedEvent unsignedEvent, @NonNull final Bytes signature) {
this(
new GossipEvent(
Objects.requireNonNull(unsignedEvent, "The unsignedEvent must not be null")
.getEventCore(),
Bytes.wrap(Objects.requireNonNull(signature, "The signature must not be null")),
Objects.requireNonNull(signature, "The signature must not be null"),
unsignedEvent.getEventTransactions()),
unsignedEvent.getMetadata());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,6 @@ public DefaultSelfEventSigner(@NonNull final KeysAndCerts keysAndCerts) {
@Override
public PlatformEvent signEvent(@NonNull final UnsignedEvent event) {
final Signature signature = new PlatformSigner(keysAndCerts).sign(event.getHash());
return new PlatformEvent(event, signature.getSignatureBytes());
return new PlatformEvent(event, signature.getBytes());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ public static void serializeSignatures(
out.writeInt(signatures.size());
for (final NodeSignature entry : signatures) {
out.writeSerializable(entry.nodeId(), false);
out.writeSerializable(entry.signature(), false);
entry.signature().serialize(out, false);
}
}

Expand All @@ -87,11 +87,7 @@ public static List<NodeSignature> deserializeSignatures(@NonNull final Serializa
if (nodeId == null) {
throw new IOException("nodeId is null");
}
final Signature signature = in.readSerializable(false, Signature::new);
if (signature == null) {
throw new IOException("signature is null");
}

final Signature signature = Signature.deserialize(in, false);
signatures.add(new NodeSignature(nodeId, signature));
}
return signatures;
Expand Down
Loading

0 comments on commit 273d6e8

Please sign in to comment.