KeyPair.java
/*
* Copyright ConsenSys AG.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.crypto;
import static com.google.common.base.Preconditions.checkNotNull;
import java.math.BigInteger;
import java.security.KeyPairGenerator;
import java.util.Arrays;
import java.util.Objects;
import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey;
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey;
/** The Key pair class. */
public class KeyPair {
private final SECPPrivateKey privateKey;
private final SECPPublicKey publicKey;
/**
* Instantiates a new Key pair.
*
* @param privateKey the private key
* @param publicKey the public key
*/
public KeyPair(final SECPPrivateKey privateKey, final SECPPublicKey publicKey) {
checkNotNull(privateKey);
checkNotNull(publicKey);
this.privateKey = privateKey;
this.publicKey = publicKey;
}
/**
* Create key pair.
*
* @param privateKey the private key
* @param curve the curve
* @param algorithm the algorithm
* @return the key pair
*/
public static KeyPair create(
final SECPPrivateKey privateKey, final ECDomainParameters curve, final String algorithm) {
return new KeyPair(privateKey, SECPPublicKey.create(privateKey, curve, algorithm));
}
/**
* Generate key pair.
*
* @param keyPairGenerator the key pair generator
* @param algorithm the algorithm
* @return the key pair
*/
public static KeyPair generate(final KeyPairGenerator keyPairGenerator, final String algorithm) {
final java.security.KeyPair rawKeyPair = keyPairGenerator.generateKeyPair();
final BCECPrivateKey privateKey = (BCECPrivateKey) rawKeyPair.getPrivate();
final BCECPublicKey publicKey = (BCECPublicKey) rawKeyPair.getPublic();
final BigInteger privateKeyValue = privateKey.getD();
// Ethereum does not use encoded public keys like bitcoin - see
// https://en.bitcoin.it/wiki/Elliptic_Curve_Digital_Signature_Algorithm for details
// Additionally, as the first bit is a constant prefix (0x04) we ignore this value
final byte[] publicKeyBytes = publicKey.getQ().getEncoded(false);
final BigInteger publicKeyValue =
new BigInteger(1, Arrays.copyOfRange(publicKeyBytes, 1, publicKeyBytes.length));
return new KeyPair(
SECPPrivateKey.create(privateKeyValue, algorithm),
SECPPublicKey.create(publicKeyValue, algorithm));
}
@Override
public int hashCode() {
return Objects.hash(privateKey, publicKey);
}
@Override
public boolean equals(final Object other) {
if (!(other instanceof KeyPair)) {
return false;
}
final KeyPair that = (KeyPair) other;
return this.privateKey.equals(that.privateKey) && this.publicKey.equals(that.publicKey);
}
@Override
public String toString() {
return ("KeyPair{privateKey: "
+ this.privateKey.toString()
+ ", publicKey: "
+ this.publicKey.toString()
+ "]");
}
/**
* Gets private key.
*
* @return the private key
*/
public SECPPrivateKey getPrivateKey() {
return privateKey;
}
/**
* Gets public key.
*
* @return the public key
*/
public SECPPublicKey getPublicKey() {
return publicKey;
}
}