93 lines
4 KiB
Java
93 lines
4 KiB
Java
package info.frostfs.sdk;
|
|
|
|
import info.frostfs.sdk.exceptions.ProcessFrostFSException;
|
|
import info.frostfs.sdk.exceptions.ValidationFrostFSException;
|
|
import org.bouncycastle.asn1.sec.SECNamedCurves;
|
|
import org.bouncycastle.asn1.sec.SECObjectIdentifiers;
|
|
import org.bouncycastle.asn1.x9.X9ECParameters;
|
|
import org.bouncycastle.crypto.params.ECDomainParameters;
|
|
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
|
|
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
|
|
import org.bouncycastle.jce.spec.ECNamedCurveSpec;
|
|
|
|
import java.security.KeyFactory;
|
|
import java.security.NoSuchAlgorithmException;
|
|
import java.security.PrivateKey;
|
|
import java.security.PublicKey;
|
|
import java.security.spec.ECParameterSpec;
|
|
import java.security.spec.ECPrivateKeySpec;
|
|
import java.security.spec.ECPublicKeySpec;
|
|
import java.security.spec.InvalidKeySpecException;
|
|
|
|
import static info.frostfs.sdk.constants.ErrorConst.COMPRESSED_PUBLIC_KEY_WRONG_LENGTH_TEMPLATE;
|
|
import static info.frostfs.sdk.constants.ErrorConst.INPUT_PARAM_IS_MISSING;
|
|
import static java.util.Objects.isNull;
|
|
import static org.bouncycastle.util.BigIntegers.fromUnsignedByteArray;
|
|
|
|
public class KeyExtension {
|
|
private static final String CURVE_NAME = "secp256r1";
|
|
private static final String SECURITY_ALGORITHM = "EC";
|
|
private static final int COMPRESSED_PUBLIC_KEY_LENGTH = 33;
|
|
|
|
private KeyExtension() {
|
|
}
|
|
|
|
public static PrivateKey loadPrivateKey(byte[] privateKey) {
|
|
checkInputValue(privateKey);
|
|
|
|
X9ECParameters params = SECNamedCurves.getByOID(SECObjectIdentifiers.secp256r1);
|
|
ECDomainParameters domain = new ECDomainParameters(
|
|
params.getCurve(), params.getG(), params.getN(), params.getH()
|
|
);
|
|
ECPrivateKeyParameters ecParams = new ECPrivateKeyParameters(fromUnsignedByteArray(privateKey), domain);
|
|
|
|
ECParameterSpec ecParameterSpec = new ECNamedCurveSpec(
|
|
CURVE_NAME, params.getCurve(), params.getG(), params.getN(), params.getH()
|
|
);
|
|
ECPrivateKeySpec privateKeySpec = new ECPrivateKeySpec(ecParams.getD(), ecParameterSpec);
|
|
try {
|
|
KeyFactory kf = KeyFactory.getInstance(SECURITY_ALGORITHM);
|
|
return kf.generatePrivate(privateKeySpec);
|
|
} catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
|
|
throw new ProcessFrostFSException(e);
|
|
}
|
|
}
|
|
|
|
public static PublicKey getPublicKeyFromBytes(byte[] publicKey) {
|
|
checkInputValue(publicKey);
|
|
|
|
if (publicKey.length != COMPRESSED_PUBLIC_KEY_LENGTH) {
|
|
throw new ValidationFrostFSException(String.format(
|
|
COMPRESSED_PUBLIC_KEY_WRONG_LENGTH_TEMPLATE, COMPRESSED_PUBLIC_KEY_LENGTH, publicKey.length
|
|
));
|
|
}
|
|
|
|
X9ECParameters secp256R1 = SECNamedCurves.getByOID(SECObjectIdentifiers.secp256r1);
|
|
ECDomainParameters domain = new ECDomainParameters(
|
|
secp256R1.getCurve(), secp256R1.getG(), secp256R1.getN(), secp256R1.getH()
|
|
);
|
|
var ecPoint = secp256R1.getCurve().decodePoint(publicKey);
|
|
var publicParams = new ECPublicKeyParameters(ecPoint, domain);
|
|
java.security.spec.ECPoint point = new java.security.spec.ECPoint(
|
|
publicParams.getQ().getRawXCoord().toBigInteger(), publicParams.getQ().getRawYCoord().toBigInteger()
|
|
);
|
|
ECParameterSpec ecParameterSpec = new ECNamedCurveSpec(
|
|
CURVE_NAME, secp256R1.getCurve(), secp256R1.getG(), secp256R1.getN(), secp256R1.getH(),
|
|
secp256R1.getSeed()
|
|
);
|
|
ECPublicKeySpec publicKeySpec = new ECPublicKeySpec(point, ecParameterSpec);
|
|
|
|
try {
|
|
KeyFactory kf = KeyFactory.getInstance(SECURITY_ALGORITHM);
|
|
return kf.generatePublic(publicKeySpec);
|
|
} catch (Exception e) {
|
|
throw new ProcessFrostFSException(e);
|
|
}
|
|
}
|
|
|
|
private static void checkInputValue(byte[] data) {
|
|
if (isNull(data) || data.length == 0) {
|
|
throw new ValidationFrostFSException(INPUT_PARAM_IS_MISSING);
|
|
}
|
|
}
|
|
}
|