Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement calculatePublicKey() in classes that extend PKCS8Key #372

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions src/main/java/com/ibm/crypto/plus/provider/ECPrivateKey.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
import java.security.AlgorithmParameters;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.ProviderException;
import java.security.PublicKey;
import java.security.spec.ECParameterSpec;
import java.security.spec.InvalidParameterSpecException;
import java.util.Arrays;
Expand Down Expand Up @@ -571,6 +573,16 @@ ECKey getOCKKey() {
return this.ecKey;
}

@Override
public PublicKey calculatePublicKey() {
try {
return new ECPublicKey(provider, ecKey);
} catch (InvalidKeyException exc) {
throw new ProviderException(
"Unexpected error calculating public key", exc);
}
}

/**
* Parse the key. Called by PKCS8Key. "key" is a byte array containing the
* Der-encoded key which resides within the parent class PKCS8Key. The
Expand Down
18 changes: 15 additions & 3 deletions src/main/java/com/ibm/crypto/plus/provider/XDHPrivateKeyImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
import java.security.InvalidKeyException;
import java.security.InvalidParameterException;
import java.security.KeyRep;
import java.security.ProviderException;
import java.security.PublicKey;
import java.security.interfaces.XECPrivateKey;
import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.NamedParameterSpec;
Expand Down Expand Up @@ -94,8 +96,8 @@ public XDHPrivateKeyImpl(OpenJCEPlusProvider provider, byte[] encoded)
try {
byte[] alteredEncoded = processEncodedPrivateKey(encoded); // Sets params, key, and algid, and alters encoded
// to fit with GSKit and sets params
int encodingSize = CurveUtil.getDEREncodingSize(curve);
this.xecKey = XECKey.createPrivateKey(provider.getOCKContext(), alteredEncoded, encodingSize);
int curveSize = CurveUtil.getCurveSize(curve);
this.xecKey = XECKey.createPrivateKey(provider.getOCKContext(), alteredEncoded, curveSize);
this.scalar = Optional.of(k);
} catch (Exception exception) {
InvalidKeyException ike = new InvalidKeyException("Failed to create XEC private key");
Expand Down Expand Up @@ -374,7 +376,7 @@ private boolean isCorrectlyFormedOctetString(byte[] keyBytes) throws IOException
return true;
}

public XECKey getOCKKey() {
XECKey getOCKKey() {
return this.xecKey;
}

Expand Down Expand Up @@ -424,6 +426,16 @@ public String getAlgorithm() {
return "XDH";
}

@Override
public PublicKey calculatePublicKey() {
try {
return new XDHPublicKeyImpl(provider, xecKey, curve);
} catch (InvalidKeyException exc) {
throw new ProviderException(
"Unexpected error calculating public key", exc);
}
}

/**
* Adds a sequence of FFDHE integers (bi1, bi2, and bi3) to the OutputStream param.
* DER added: SEQUENCE[INTEGER,INTEGER,INTEGER]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,54 @@
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Arrays;
import org.junit.Assert;
import org.junit.jupiter.api.Test;
import sun.security.util.InternalPrivateKey;
import static org.junit.Assert.assertTrue;

public class BaseTestECKeyImportInterop extends BaseTestJunit5Interop {

static final byte[] origMsg = "this is the original message to be signed".getBytes();

@Test
public void testCreateKeyPairECGenParamImportCalculatePublic() throws Exception {
doCreateKeyPairECGenParamImportCalculatePublic(getProviderName(), getInteropProviderName());
doCreateKeyPairECGenParamImportCalculatePublic(getInteropProviderName(), getProviderName());
}

public void doCreateKeyPairECGenParamImportCalculatePublic(String generateProviderName,
String importProviderName) throws Exception {

//final String methodName = "testECGenParamImportHardcoded";
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("EC", generateProviderName);

keyPairGen.initialize(256);
KeyPair keyPair = keyPairGen.generateKeyPair();
PrivateKey privateKey = keyPair.getPrivate();
PublicKey publicKey = keyPair.getPublic();

// Recreate private key from encoding.
byte[] privKeyBytes = privateKey.getEncoded();
KeyFactory keyFactory = KeyFactory.getInstance("EC", importProviderName);
EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(privKeyBytes);
privateKey = keyFactory.generatePrivate(privateKeySpec);

// Get public key bytes from private.
byte[] calculatedPublicKey = ((InternalPrivateKey) privateKey).calculatePublicKey().getEncoded();

// Get public key bytes from original public key.
byte[] publicKeyBytes = publicKey.getEncoded();

System.out.println("---- Comparing EC public key from KeyPair vs calculated from private key ----");
System.out.println("EC public key from Keypair from " + generateProviderName + ": "
+ BaseUtils.bytesToHex(publicKeyBytes));
System.out.println("EC public key from calculatePublicKey() from " + importProviderName + ": "
+ BaseUtils.bytesToHex(calculatedPublicKey));

// The original and calculated public keys should be the same
Assert.assertArrayEquals(calculatedPublicKey, publicKeyBytes);
}

@Test
public void testCreateKeyPairECGenParamImport() throws Exception {
doCreateKeyPairECGenParamImport(getProviderName(), getInteropProviderName());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,19 @@
import java.security.InvalidAlgorithmParameterException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.ProviderException;
import java.security.PublicKey;
import java.security.interfaces.ECPrivateKey;
import java.security.interfaces.ECPublicKey;
import java.security.spec.ECGenParameterSpec;
import java.security.spec.ECParameterSpec;
import java.security.spec.ECPoint;
import java.security.spec.EllipticCurve;
import org.junit.Assert;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import sun.security.util.InternalPrivateKey;
import static org.junit.Assert.assertTrue;

public class BaseTestECKeyPairGenerator extends BaseTestJunit5 {
Expand Down Expand Up @@ -101,6 +105,23 @@ public void compareEcParameterSpec(ECParameterSpec ecParameterSpecPub,

}

@Test
public void testECPrivateKey_calculatePublicKey() throws Exception {
kpg.initialize(256);
KeyPair kp = kpg.generateKeyPair();

PublicKey ecpu = kp.getPublic();
PrivateKey ecpr = kp.getPrivate();

byte[] originalEncoded = ecpu.getEncoded();
byte[] calculatedEncoded = ((InternalPrivateKey) ecpr).calculatePublicKey().getEncoded();

System.out.println("---- Comparing EC public key from KeyPair vs calculated from private key ----");
System.out.println("EC public key from Keypair: " + BaseUtils.bytesToHex(originalEncoded));
System.out.println("EC public key from calculatePublicKey(): " + BaseUtils.bytesToHex(calculatedEncoded));
Assert.assertArrayEquals(originalEncoded, calculatedEncoded);
}

@Test
public void testECKeyGenCurves_secp192k1() throws Exception {
generictestECKeyGenCurve("secp192k1");
Expand Down
46 changes: 46 additions & 0 deletions src/test/java/ibm/jceplus/junit/base/BaseTestXDHInterop.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,17 @@
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.EncodedKeySpec;
import java.security.spec.NamedParameterSpec;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
import org.junit.Assert;
import org.junit.jupiter.api.Test;
import sun.security.util.InternalPrivateKey;

public class BaseTestXDHInterop extends BaseTestJunit5Interop {

Expand All @@ -29,6 +33,48 @@ public class BaseTestXDHInterop extends BaseTestJunit5Interop {
String openJDK_private_X448 = "MEYCAQAwBwYDK2VvBQAEOOJFsgLYxgAIEWuN1FLAGWDzGQRSataAbPLDc1wv5aky4T8hevyWbYdhggc1OCcqQ93gY8rqVTDb";
// OpenJDK does not currently support FFDHE hence interop testing for FFDHE is not possible

@Test
public void testCreateKeyPairXDHGenParamImportCalculatePublic() throws Exception {
if (!"BC".equals(getInteropProviderName())) {
doCreateKeyPairXDHGenParamImportCalculatePublic(getProviderName(), getInteropProviderName());
doCreateKeyPairXDHGenParamImportCalculatePublic(getInteropProviderName(), getProviderName());
}

}

public void doCreateKeyPairXDHGenParamImportCalculatePublic(String generateProviderName,
String importProviderName) throws Exception {

//final String methodName = "testECGenParamImportHardcoded";
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("XDH", generateProviderName);

keyPairGen.initialize(255);
KeyPair keyPair = keyPairGen.generateKeyPair();
PrivateKey privateKey = keyPair.getPrivate();
PublicKey publicKey = keyPair.getPublic();

// Recreate private key from encoding.
byte[] privKeyBytes = privateKey.getEncoded();
KeyFactory keyFactory = KeyFactory.getInstance("XDH", importProviderName);
EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(privKeyBytes);
privateKey = keyFactory.generatePrivate(privateKeySpec);

// Get public key bytes from private.
byte[] calculatedPublicKey = ((InternalPrivateKey) privateKey).calculatePublicKey().getEncoded();

// Get public key bytes from original public key.
byte[] publicKeyBytes = publicKey.getEncoded();

System.out.println("---- Comparing XDH public key from KeyPair vs calculated from private key ----");
System.out.println("XDH public key from Keypair from " + generateProviderName + ": "
+ BaseUtils.bytesToHex(publicKeyBytes));
System.out.println("XDH public key from calculatePublicKey() from " + importProviderName + ": "
+ BaseUtils.bytesToHex(calculatedPublicKey));

// The original and calculated public keys should be the same
Assert.assertArrayEquals(calculatedPublicKey, publicKeyBytes);
}

@Test
public void testXDHInterop_X25519_OpenJDK() throws Exception {
byte[] openJDK_public_bytes = Base64.getDecoder().decode(openJDK_public_X25519);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,15 @@

import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.interfaces.XECPrivateKey;
import java.security.interfaces.XECPublicKey;
import java.security.spec.NamedParameterSpec;
import org.junit.Assert;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import sun.security.util.InternalPrivateKey;

public class BaseTestXDHKeyPairGenerator extends BaseTestJunit5 {

Expand Down Expand Up @@ -82,6 +86,23 @@ public void doXECKeyGen(int keypairSize) throws Exception {
//System.out.println("ECPrivate: " + ecpr.getS());
}

@Test
public void testXDHPrivateKey_calculatePublicKey() throws Exception {
kpg.initialize(255);
KeyPair kp = kpg.generateKeyPair();

PublicKey ecpu = kp.getPublic();
PrivateKey ecpr = kp.getPrivate();

byte[] originalEncoded = ecpu.getEncoded();
byte[] calculatedEncoded = ((InternalPrivateKey) ecpr).calculatePublicKey().getEncoded();

System.out.println("---- Comparing XDH public key from KeyPair vs calculated from private key ----");
System.out.println("XDH public key from Keypair: " + BaseUtils.bytesToHex(originalEncoded));
System.out.println("XDH public key from calculatePublicKey(): " + BaseUtils.bytesToHex(calculatedEncoded));
Assert.assertArrayEquals(originalEncoded, calculatedEncoded);
}

@Test
public void testXECKeyGenCurves() throws Exception {
generictestXECKeyGenCurve("X25519");
Expand Down