Skip to content

Commit

Permalink
Merge branch 'df/v3-dev-preview' of github.com:XRPLF/XRPL4j into rele…
Browse files Browse the repository at this point in the history
…ases/v3.0-rc
  • Loading branch information
sappenin committed Oct 10, 2022
2 parents 6d958ee + 3a48818 commit 698f05d
Show file tree
Hide file tree
Showing 71 changed files with 2,075 additions and 358 deletions.
11 changes: 4 additions & 7 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -202,13 +202,10 @@
</dependency>
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-core</artifactId>
<version>${feign.version}</version>
</dependency>
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-jackson</artifactId>
<artifactId>feign-bom</artifactId>
<version>${feign.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
Expand Down Expand Up @@ -329,7 +326,7 @@
<feign.version>11.6</feign.version>
<slf4j.version>1.7.30</slf4j.version>
<junit-jupiter.version>5.7.1</junit-jupiter.version>
<guava.version>29.0-jre</guava.version>
<guava.version>31.1-jre</guava.version>
</properties>

<modules>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,11 @@

/**
* A service to help with interactions involving XRPL addresses.
*
* @deprecated This interface will be removed in a future version. Prefer
* {@link org.xrpl.xrpl4j.crypto.core.keys.KeyPairService} instead.
*/
@Deprecated
public class BcAddressUtils implements AddressUtils {

private static final BcAddressUtils INSTANCE = new BcAddressUtils();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,6 @@
import com.google.common.collect.Sets;
import com.google.common.hash.Hashing;
import org.bouncycastle.crypto.digests.SHA256Digest;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.crypto.params.Ed25519PrivateKeyParameters;
import org.bouncycastle.crypto.params.Ed25519PublicKeyParameters;
import org.bouncycastle.crypto.signers.ECDSASigner;
import org.bouncycastle.crypto.signers.Ed25519Signer;
import org.bouncycastle.crypto.signers.HMacDSAKCalculator;
Expand All @@ -23,7 +19,6 @@
import org.xrpl.xrpl4j.crypto.bc.keys.Ed25519KeyPairService;
import org.xrpl.xrpl4j.crypto.bc.keys.Secp256k1KeyPairService;
import org.xrpl.xrpl4j.crypto.core.AddressUtils;
import org.xrpl.xrpl4j.crypto.core.HashingUtils;
import org.xrpl.xrpl4j.crypto.core.KeyMetadata;
import org.xrpl.xrpl4j.crypto.core.ServerSecret;
import org.xrpl.xrpl4j.crypto.core.ServerSecretSupplier;
Expand All @@ -44,7 +39,6 @@
import org.xrpl.xrpl4j.model.jackson.ObjectMapperFactory;
import org.xrpl.xrpl4j.model.transactions.Transaction;

import java.math.BigInteger;
import java.security.KeyStore;
import java.util.Arrays;
import java.util.Objects;
Expand Down Expand Up @@ -354,6 +348,7 @@ private static class SingleKeyDelegatedTransactionSigner extends AbstractDelegat
private final Ed25519Signer ed25519Signer;
private final ECDSASigner ecdsaSigner;
private final PrivateKey privateKey;
private final BcSignatureService bcSignatureService;

private SingleKeyDelegatedTransactionSigner(
PrivateKey privateKey,
Expand All @@ -364,59 +359,27 @@ private SingleKeyDelegatedTransactionSigner(
this.ed25519Signer = new Ed25519Signer();
this.ecdsaSigner = new ECDSASigner(new HMacDSAKCalculator(new SHA256Digest()));
this.privateKey = privateKey;
this.bcSignatureService = new BcSignatureService(
signatureUtils,
addressUtils,
this.ed25519Signer,
this.ecdsaSigner
);
}

@Override
protected synchronized Signature edDsaSign(
final KeyMetadata privateKeyMetadata, final UnsignedByteArray signableTransactionBytes
) {
Objects.requireNonNull(privateKeyMetadata);
Objects.requireNonNull(signableTransactionBytes);

Ed25519PrivateKeyParameters privateKeyParameters = BcKeyUtils.toEd25519PrivateKeyParams(privateKey);

ed25519Signer.reset();
ed25519Signer.init(true, privateKeyParameters);
ed25519Signer.update(
signableTransactionBytes.toByteArray(), 0, signableTransactionBytes.getUnsignedBytes().size()
);

final UnsignedByteArray sigBytes = UnsignedByteArray.of(ed25519Signer.generateSignature());
return Signature.builder()
.value(sigBytes)
.build();
return bcSignatureService.edDsaSign(privateKey, signableTransactionBytes);
}

@SuppressWarnings("checkstyle:LocalVariableName")
@Override
protected synchronized Signature ecDsaSign(
final KeyMetadata keyMetadata, final UnsignedByteArray signableTransactionBytes
) {
Objects.requireNonNull(keyMetadata);
Objects.requireNonNull(signableTransactionBytes);

final UnsignedByteArray messageHash = HashingUtils.sha512Half(signableTransactionBytes);

final ECPrivateKeyParameters parameters = BcKeyUtils.toEcPrivateKeyParams(privateKey);

ecdsaSigner.init(true, parameters);
final BigInteger[] signatures = ecdsaSigner.generateSignature(messageHash.toByteArray());
final BigInteger r = signatures[0];
BigInteger s = signatures[1];
final BigInteger otherS = Secp256k1.EC_DOMAIN_PARAMETERS.getN().subtract(s);
if (s.compareTo(otherS) > 0) {
s = otherS;
}

final EcDsaSignature sig = EcDsaSignature.builder()
.r(r)
.s(s)
.build();

UnsignedByteArray sigBytes = sig.der();
return Signature.builder()
.value(sigBytes)
.build();
return bcSignatureService.ecDsaSign(privateKey, signableTransactionBytes);
}

@Override
Expand All @@ -435,6 +398,7 @@ private static class SingleKeyDelegatedTransactionVerifier extends AbstractDeleg
private final Ed25519Signer ed25519Signer;
private final ECDSASigner ecdsaSigner;
private final PrivateKey privateKey;
private final BcSignatureService bcSignatureService;

public SingleKeyDelegatedTransactionVerifier(
PrivateKey privateKey,
Expand All @@ -445,6 +409,12 @@ public SingleKeyDelegatedTransactionVerifier(
this.ed25519Signer = new Ed25519Signer();
this.ecdsaSigner = new ECDSASigner(new HMacDSAKCalculator(new SHA256Digest()));
this.privateKey = privateKey;
this.bcSignatureService = new BcSignatureService(
signatureUtils,
addressUtils,
this.ed25519Signer,
this.ecdsaSigner
);
}

@Override
Expand All @@ -453,21 +423,10 @@ protected synchronized boolean edDsaVerify(
final UnsignedByteArray signableTransactionBytes,
final Signature transactionSignature
) {
Objects.requireNonNull(keyMetadata);
Objects.requireNonNull(signableTransactionBytes);
Objects.requireNonNull(transactionSignature);

final PublicKey publicKey = this.getPublicKey(keyMetadata);
final Ed25519PublicKeyParameters bcPublicKey = BcKeyUtils.toEd25519PublicKeyParameters(
publicKey);

ed25519Signer.reset();
ed25519Signer.init(false, bcPublicKey);
ed25519Signer.update(signableTransactionBytes.toByteArray(), 0,
signableTransactionBytes.getUnsignedBytes().size());

return ed25519Signer.verifySignature(
transactionSignature.value().toByteArray()
return bcSignatureService.edDsaVerify(
this.getPublicKey(keyMetadata),
signableTransactionBytes,
transactionSignature
);
}

Expand All @@ -477,21 +436,11 @@ protected synchronized boolean ecDsaVerify(
final UnsignedByteArray signableTransactionBytes,
final Signature transactionSignature
) {
Objects.requireNonNull(keyMetadata);
Objects.requireNonNull(signableTransactionBytes);
Objects.requireNonNull(transactionSignature);

final PublicKey publicKey = this.getPublicKey(keyMetadata);
final ECPublicKeyParameters bcPublicKey = BcKeyUtils.toEcPublicKeyParameters(publicKey);

UnsignedByteArray messageHash = HashingUtils.sha512Half(signableTransactionBytes);
EcDsaSignature sig = EcDsaSignature.fromDer(transactionSignature.value().toByteArray());
if (sig == null) {
return false;
}

ecdsaSigner.init(false, bcPublicKey);
return ecdsaSigner.verifySignature(messageHash.toByteArray(), sig.r(), sig.s());
return bcSignatureService.ecDsaVerify(
this.getPublicKey(keyMetadata),
signableTransactionBytes,
transactionSignature
);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,4 +150,4 @@ default void isStrictlyCanonical() {
Preconditions.checkArgument(order.subtract(s).compareTo(s) > -1);

}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ public static WalletFactory getInstance() {
return INSTANCE;
}

@Deprecated
@Override
public SeedWalletGenerationResult randomWalletEd25519() {
Seed seed = ed25519KeyPairService.generateSeed();
Expand All @@ -57,6 +58,7 @@ public SeedWalletGenerationResult randomWalletEd25519() {
return SeedWalletGenerationResult.builder().seed(seed).wallet(wallet).build();
}

@Deprecated
@Override
public SeedWalletGenerationResult randomWalletSecp256k1() {
Seed seed = secp256k1KeyPairService.generateSeed();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ protected synchronized Signature edDsaSign(
Objects.requireNonNull(signableTransactionBytes);

Ed25519PrivateKeyParameters privateKeyParameters = new Ed25519PrivateKeyParameters(
BaseEncoding.base16().decode(privateKey.base16Encoded().substring(2)), // Remove ED prefix byte
BaseEncoding.base16().decode(privateKey.base16Encoded().substring(2).toUpperCase()), // Remove ED prefix byte
0
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.xrpl.xrpl4j.crypto.bc.wallet.BcWalletFactory;
import org.xrpl.xrpl4j.crypto.core.AddressUtils;
import org.xrpl.xrpl4j.crypto.core.keys.Passphrase;
import org.xrpl.xrpl4j.crypto.core.keys.PublicKey;
import org.xrpl.xrpl4j.crypto.core.keys.Seed;
Expand All @@ -16,16 +17,25 @@
class BcAddressUtilsTest {

@Test
public void deriveAddressWithNull() {
void deriveAddressWithNull() {
Assertions.assertThrows(NullPointerException.class, () -> BcAddressUtils.getInstance().deriveAddress(null));
}

@Test
public void deriveAddress() {
void deriveAddress() {
PublicKey publicKey = BcWalletFactory.getInstance()
.fromSeed(Seed.ed25519SeedFromPassphrase(Passphrase.of("hello"))).publicKey();
Address address = BcAddressUtils.getInstance().deriveAddress(publicKey);
assertThat(address.value()).isEqualTo("rwGWYtRR6jJJJq7FKQg74YwtkiPyUqJ466");
}

@Test
void testAddressConstants() {
assertThat(AddressUtils.ACCOUNT_ZERO.value()).isEqualTo("rrrrrrrrrrrrrrrrrrrrrhoLvTp");
assertThat(AddressUtils.ACCOUNT_ONE.value()).isEqualTo("rrrrrrrrrrrrrrrrrrrrBZbvji");
assertThat(AddressUtils.GENESIS_ACCOUNT.value()).isEqualTo("rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh");
assertThat(AddressUtils.NAME_RESERVATION_BLACKHOLD.value()).isEqualTo("rrrrrrrrrrrrrrrrrNAMEtxvNvQ");
assertThat(AddressUtils.NAN_ADDRESS.value()).isEqualTo("rrrrrrrrrrrrrrrrrrrn5RM1rHd");
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import org.junit.jupiter.api.Test;
import org.xrpl.xrpl4j.codec.addresses.UnsignedByteArray;
import org.xrpl.xrpl4j.crypto.bc.BcAddressUtils;
import org.xrpl.xrpl4j.crypto.core.keys.Base58EncodedSecret;
import org.xrpl.xrpl4j.crypto.core.keys.Entropy;
import org.xrpl.xrpl4j.crypto.core.keys.KeyPair;
import org.xrpl.xrpl4j.crypto.core.keys.PrivateKey;
Expand Down Expand Up @@ -50,7 +51,7 @@ void deriveKeyPairFromNull() {

@Test
public void deriveKeyPair() {
Seed seed = Seed.fromBase58EncodedSecret("sEdSvUyszZFDFkkxQLm18ry3yeZ2FDM");
Seed seed = Seed.fromBase58EncodedSecret(Base58EncodedSecret.of("sEdSvUyszZFDFkkxQLm18ry3yeZ2FDM"));
KeyPair keyPair = keyPairService.deriveKeyPair(seed);
KeyPair expectedKeyPair = KeyPair.builder()
.privateKey(PrivateKey.of(UnsignedByteArray.of(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import org.junit.jupiter.api.Test;
import org.xrpl.xrpl4j.codec.addresses.UnsignedByteArray;
import org.xrpl.xrpl4j.crypto.bc.BcAddressUtils;
import org.xrpl.xrpl4j.crypto.core.keys.Base58EncodedSecret;
import org.xrpl.xrpl4j.crypto.core.keys.Entropy;
import org.xrpl.xrpl4j.crypto.core.keys.KeyPair;
import org.xrpl.xrpl4j.crypto.core.keys.PrivateKey;
Expand Down Expand Up @@ -50,7 +51,7 @@ void deriveKeyPairFromNull() {

@Test
public void deriveSecp256k1KeyPair() {
Seed seed = Seed.fromBase58EncodedSecret("sp5fghtJtpUorTwvof1NpDXAzNwf5");
Seed seed = Seed.fromBase58EncodedSecret(Base58EncodedSecret.of("sp5fghtJtpUorTwvof1NpDXAzNwf5"));
KeyPair keyPair = keyPairService.deriveKeyPair(seed);
KeyPair expectedKeyPair = KeyPair.builder()
.privateKey(PrivateKey.of(UnsignedByteArray.of(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
package org.xrpl.xrpl4j.crypto.bc.signing;

import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import com.google.common.io.BaseEncoding;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.xrpl.xrpl4j.codec.addresses.UnsignedByte;
import org.xrpl.xrpl4j.codec.addresses.UnsignedByteArray;

import java.math.BigInteger;

Expand Down Expand Up @@ -39,8 +43,58 @@ void der() {
}

@Test
@Disabled
void isStrictlyCanonical() {
// TODO: Add coverage.
void badDerThrowsWhenFormingSignature() {
assertThrows(
RuntimeException.class,
() -> EcDsaSignature.fromDer(new byte[] {1, 2, 3, 4})
);
}

@Test
void ecDsaSignatureWithR0() {
IllegalArgumentException illegalArgumentException = assertThrows(
IllegalArgumentException.class,
() -> EcDsaSignature.builder()
.r(BigInteger.ZERO)
.s(BigInteger.ONE)
.build()
);
assertThat(illegalArgumentException.getMessage()).isEqualTo("r cannot be 0.");
}

@Test
void ecDsaSignatureWithS0() {
IllegalArgumentException illegalArgumentException = assertThrows(
IllegalArgumentException.class,
() -> EcDsaSignature.builder()
.r(BigInteger.ONE)
.s(BigInteger.ZERO)
.build()
);
assertThat(illegalArgumentException.getMessage()).isEqualTo("s cannot be 0.");
}

@Test
void ecDsaSignatureWithRNegativeThrows() {
IllegalArgumentException illegalArgumentException = assertThrows(
IllegalArgumentException.class,
() -> EcDsaSignature.builder()
.r(BigInteger.ONE.negate())
.s(BigInteger.valueOf(2))
.build()
);
assertThat(illegalArgumentException.getMessage()).isEqualTo("r cannot be negative.");
}

@Test
void ecDsaSignatureWithSNegativeThrows() {
IllegalArgumentException illegalArgumentException = assertThrows(
IllegalArgumentException.class,
() -> EcDsaSignature.builder()
.r(BigInteger.valueOf(2))
.s(BigInteger.ONE.negate())
.build()
);
assertThat(illegalArgumentException.getMessage()).isEqualTo("s cannot be negative.");
}
}
Loading

0 comments on commit 698f05d

Please sign in to comment.