Skip to content

Commit

Permalink
Add sequenceNumber to signatures
Browse files Browse the repository at this point in the history
  • Loading branch information
Hellblazer committed Nov 20, 2023
1 parent 8b8e545 commit b88b17a
Show file tree
Hide file tree
Showing 31 changed files with 635 additions and 679 deletions.
6 changes: 3 additions & 3 deletions choam/src/main/java/com/salesforce/apollo/choam/CHOAM.java
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ public static List<Transaction> toGenesisData(List<? extends Message> initializa
public static List<Transaction> toGenesisData(List<? extends Message> initializationData,
DigestAlgorithm digestAlgo, SignatureAlgorithm sigAlgo) {
var source = digestAlgo.getOrigin();
SignerImpl signer = new SignerImpl(sigAlgo.generateKeyPair().getPrivate());
SignerImpl signer = new SignerImpl(sigAlgo.generateKeyPair().getPrivate(), ULong.MIN);
AtomicInteger nonce = new AtomicInteger();
return initializationData.stream()
.map(m -> (Message) m)
Expand Down Expand Up @@ -1203,7 +1203,7 @@ private class Associate extends Administration {
params.digestAlgorithm().digest(nextView.consensusKeyPair.getPublic().getEncoded()),
params.digestAlgorithm().digest(nextView.member.getSignature().toByteString()), viewId,
params.member().getId());
Signer signer = new SignerImpl(nextView.consensusKeyPair.getPrivate());
Signer signer = new SignerImpl(nextView.consensusKeyPair.getPrivate(), ULong.MIN);
viewContext = new ViewContext(context, params, signer, validators, constructBlock());
producer = new Producer(viewContext, head.get(), checkpoint.get(), comm, getLabel());
producer.start();
Expand Down Expand Up @@ -1248,7 +1248,7 @@ private Formation() {
params.digestAlgorithm().digest(c.consensusKeyPair.getPublic().getEncoded()),
params.digestAlgorithm().digest(c.member.getSignature().toByteString()),
params.member().getId());
Signer signer = new SignerImpl(c.consensusKeyPair.getPrivate());
Signer signer = new SignerImpl(c.consensusKeyPair.getPrivate(), ULong.MIN);
ViewContext vc = new GenesisContext(formation, params, signer, constructBlock());
assembly = new GenesisAssembly(vc, comm, next.get().member, getLabel());
nextViewId.set(params.genesisViewId());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,8 @@ public boolean validate(HexBloom diadem, Digest initial) {
byte[] buf = state.get(i);
accumulator.add(algorithm.digest(buf));
});
var candidates = accumulator.wrappedCrowns();
for (int i = 0; i < crowns.size(); i++) {
var candidates = accumulator.wrappedCrowns();
if (!crowns.get(i).equals(candidates.get(i))) {
LoggerFactory.getLogger(CheckpointState.class)
.warn("Crown[{}] expected: {} found: {}", i, crowns.get(i), candidates.get(i));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import com.salesforce.apollo.stereotomy.StereotomyImpl;
import com.salesforce.apollo.stereotomy.mem.MemKERL;
import com.salesforce.apollo.stereotomy.mem.MemKeyStore;
import org.joou.ULong;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
Expand Down Expand Up @@ -164,8 +165,8 @@ public ViewMember answer(InvocationOnMock invocation) throws Throwable {
Router router = communications.get(m);
ViewContext view = new ViewContext(context, params.build(
RuntimeParameters.newBuilder().setContext(context).setMember(sm).setCommunications(router).build()),
new Signer.SignerImpl(consensusPairs.get(m).getPrivate()), validators,
null);
new Signer.SignerImpl(consensusPairs.get(m).getPrivate(), ULong.MIN),
validators, null);
views.put(m, view);
var ds = dataSources.get(m);
var com = comms.get(m);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,35 +6,26 @@
*/
package com.salesforce.apollo.crypto;

import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.edec.EdECObjectIdentifiers;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import org.joou.ULong;

import java.io.IOException;
import java.io.InputStream;
import java.security.GeneralSecurityException;
import java.security.InvalidAlgorithmParameterException;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.Signature;
import java.security.*;
import java.security.interfaces.EdECPublicKey;
import java.security.spec.EdECPrivateKeySpec;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.NamedParameterSpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Arrays;

import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.edec.EdECObjectIdentifiers;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;

/**
* common operations and state per algorithm.
*
* @author hal.hildebrand
*
* @author hal.hildebrand
*/
public class EdDSAOperations {

Expand All @@ -51,45 +42,26 @@ protected Signature initialValue() {
}
}
};

private static void reverse(byte[] arr) {
var i = 0;
var j = arr.length - 1;

while (i < j) {
swap(arr, i, j);
i++;
j--;
}
}

private static void swap(byte[] arr, int i, int j) {
var tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}

private final ASN1ObjectIdentifier curveId;
private final KeyFactory keyFactory;
private final KeyPairGenerator keyPairGenerator;
private final NamedParameterSpec parameterSpec;

private final SignatureAlgorithm signatureAlgorithm;
private final ASN1ObjectIdentifier curveId;
private final KeyFactory keyFactory;
private final KeyPairGenerator keyPairGenerator;
private final NamedParameterSpec parameterSpec;
private final SignatureAlgorithm signatureAlgorithm;

public EdDSAOperations(SignatureAlgorithm signatureAlgorithm) {
try {
this.signatureAlgorithm = signatureAlgorithm;

var curveName = signatureAlgorithm.curveName().toLowerCase();
parameterSpec = switch (curveName) {
case "ed25519" -> NamedParameterSpec.ED25519;
case "ed448" -> NamedParameterSpec.ED448;
default -> throw new RuntimeException("Unknown Edwards curve: " + curveName);
case "ed25519" -> NamedParameterSpec.ED25519;
case "ed448" -> NamedParameterSpec.ED448;
default -> throw new RuntimeException("Unknown Edwards curve: " + curveName);
};
curveId = switch (curveName) {
case "ed25519" -> EdECObjectIdentifiers.id_Ed25519;
case "ed448" -> EdECObjectIdentifiers.id_Ed448;
default -> throw new RuntimeException("Unknown Edwards curve: " + signatureAlgorithm);
case "ed25519" -> EdECObjectIdentifiers.id_Ed25519;
case "ed448" -> EdECObjectIdentifiers.id_Ed448;
default -> throw new RuntimeException("Unknown Edwards curve: " + signatureAlgorithm);
};

keyPairGenerator = KeyPairGenerator.getInstance(EDDSA_ALGORITHM_NAME);
Expand All @@ -100,6 +72,23 @@ public EdDSAOperations(SignatureAlgorithm signatureAlgorithm) {
}
}

private static void reverse(byte[] arr) {
var i = 0;
var j = arr.length - 1;

while (i < j) {
swap(arr, i, j);
i++;
j--;
}
}

private static void swap(byte[] arr, int i, int j) {
var tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}

public byte[] encode(PublicKey publicKey) {
var point = ((EdECPublicKey) publicKey).getPoint();
var encodedPoint = point.getY().toByteArray();
Expand Down Expand Up @@ -151,7 +140,7 @@ public PublicKey publicKey(byte[] bytes) {
}
}

public JohnHancock sign(PrivateKey[] privateKeys, InputStream is) {
public JohnHancock sign(PrivateKey[] privateKeys, InputStream is, ULong sequenceNumber) {
byte[][] signatures = new byte[privateKeys.length][];
try {
int i = 0;
Expand All @@ -169,14 +158,14 @@ public JohnHancock sign(PrivateKey[] privateKeys, InputStream is) {
signatures[i] = sig.sign();
i++;
}
return new JohnHancock(signatureAlgorithm, signatures);
return new JohnHancock(signatureAlgorithm, signatures, sequenceNumber);
} catch (GeneralSecurityException e) {
throw new IllegalArgumentException("Cannot sign", e);
}
}

public JohnHancock signature(byte[] signatureBytes) {
return new JohnHancock(signatureAlgorithm, signatureBytes);
public JohnHancock signature(byte[] signatureBytes, ULong sequenceNumber) {
return new JohnHancock(signatureAlgorithm, signatureBytes, sequenceNumber);
}

public boolean verify(PublicKey publicKey, byte[] bytes, InputStream is) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,13 @@
*/
package com.salesforce.apollo.crypto;

import com.google.protobuf.ByteString;
import com.salesfoce.apollo.cryptography.proto.Sig;
import com.salesforce.apollo.crypto.Verifier.Filtered;
import com.salesforce.apollo.utils.Hex;
import org.joou.ULong;
import org.slf4j.LoggerFactory;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
Expand All @@ -15,46 +22,41 @@
import java.util.Map;
import java.util.Objects;

import org.slf4j.LoggerFactory;

import com.google.protobuf.ByteString;
import com.salesfoce.apollo.cryptography.proto.Sig;
import com.salesforce.apollo.crypto.Verifier.Filtered;
import com.salesforce.apollo.utils.Hex;

/**
* A signature
*
* @author hal.hildebrand
*
* @author hal.hildebrand
*/
public class JohnHancock {

public static JohnHancock from(Sig signature) {
return new JohnHancock(signature);
}

public static JohnHancock of(Sig signature) {
return new JohnHancock(signature);
}

private final ULong sequenceNumber;
private final SignatureAlgorithm algorithm;
private final byte[][] bytes;

public JohnHancock(Sig sig) {
this.algorithm = SignatureAlgorithm.fromSignatureCode(sig.getCode());
bytes = new byte[sig.getSignaturesCount()][];
sequenceNumber = ULong.valueOf(sig.getSequenceNumber());
int i = 0;
sig.getSignaturesList().forEach(bs -> bytes[i] = bs.toByteArray());
}

public JohnHancock(SignatureAlgorithm algorithm, byte[] bytes) {
this(algorithm, new byte[][] { bytes });
public JohnHancock(SignatureAlgorithm algorithm, byte[] bytes, ULong sequenceNumber) {
this(algorithm, new byte[][] { bytes }, sequenceNumber);
}

public JohnHancock(SignatureAlgorithm algorithm, byte[][] bytes) {
public JohnHancock(SignatureAlgorithm algorithm, byte[][] bytes, ULong sequenceNumber) {
this.algorithm = algorithm;
this.bytes = bytes;
this.sequenceNumber = sequenceNumber;
}

public static JohnHancock from(Sig signature) {
return new JohnHancock(signature);
}

public static JohnHancock of(Sig signature) {
return new JohnHancock(signature);
}

@Override
Expand Down Expand Up @@ -87,7 +89,7 @@ public Filtered filter(SigningThreshold threshold, Map<Integer, PublicKey> keys,

int[] arrIndexes = verifiedSignatures.stream().mapToInt(i -> i.intValue()).toArray();
return new Filtered(SigningThreshold.thresholdMet(threshold, arrIndexes), arrIndexes.length,
new JohnHancock(algorithm, filtered));
new JohnHancock(algorithm, filtered, sequenceNumber));
}

public SignatureAlgorithm getAlgorithm() {
Expand All @@ -113,22 +115,23 @@ public int signatureCount() {

public Digest toDigest(DigestAlgorithm digestAlgorithm) {
if (digestAlgorithm.digestLength() * 2 != algorithm.signatureLength()) {
throw new IllegalArgumentException("Cannot convert to a hash, as digest and signature length are not compatible");
throw new IllegalArgumentException(
"Cannot convert to a hash, as digest and signature length are not compatible");
}
Digest combined = digestAlgorithm.getOrigin();
for (byte[] segment : bytes) {
combined = combined.xor(new Digest(digestAlgorithm,
Arrays.copyOf(segment, digestAlgorithm.digestLength())));
combined = combined.xor(new Digest(digestAlgorithm,
Arrays.copyOfRange(segment, digestAlgorithm.digestLength(),
segment.length)));
combined = combined.xor(
new Digest(digestAlgorithm, Arrays.copyOf(segment, digestAlgorithm.digestLength())));
combined = combined.xor(
new Digest(digestAlgorithm, Arrays.copyOfRange(segment, digestAlgorithm.digestLength(), segment.length)));
}
return combined;
}

public Sig toSig() {
return Sig.newBuilder()
.setCode(algorithm.signatureCode())
.setSequenceNumber(sequenceNumber.longValue())
.addAllSignatures(Arrays.asList(bytes).stream().map(b -> ByteString.copyFrom(b)).toList())
.build();
}
Expand Down
Loading

0 comments on commit b88b17a

Please sign in to comment.