Skip to content
Merged
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
41 changes: 39 additions & 2 deletions kse/src/main/java/org/kse/crypto/jwk/JwkUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -422,7 +422,7 @@ private static PublicKey toPublicKey(OctetKeyPair okp) throws CryptoException {
* @param publicKey The public key to export.
* @return True if the public key can be exported to JWK.
*/
public static boolean isPublicKeyTypeExportable(PublicKey publicKey) {
public static boolean isJwkSupported(PublicKey publicKey) {
try {
switch (KeyPairUtil.getKeyPairType(publicKey)) {
case ED448:
Expand All @@ -440,7 +440,44 @@ public static boolean isPublicKeyTypeExportable(PublicKey publicKey) {
return false;
}
} catch (Exception e) {
throw JwkExporterException.notSupported(publicKey.getAlgorithm(), null);
// The goal of this method is to determine if a public key can be exported.
// Throwing an exception, while providing details for troubleshooting, does
// not help the user. It prevents them from using the OpenSSL format for
// export since an exception is thrown when checking for JWK support.
// Therefore, just return false so that the user is not blocked.
return false;
}
}

/**
* Determines if the private key is exportable to JWK.
*
* @param privateKey The private key to export.
* @return True if the private key can be exported to JWK.
*/
public static boolean isJwkSupported(PrivateKey privateKey) {
try {
switch (KeyPairUtil.getKeyPairType(privateKey)) {
case ED448:
case ED25519:
case X25519:
case X448:
case RSA:
return true;
case EC:
KeyInfo keyInfo = KeyPairUtil.getKeyInfo(privateKey);
String detailedAlgorithm = keyInfo.getDetailedAlgorithm();
return ECKeyExporter.supportsCurve(detailedAlgorithm);
default:
return false;
}
} catch (Exception e) {
// The goal of this method is to determine if a private key can be exported.
// Throwing an exception, while providing details for troubleshooting, does
// not help the user. It prevents them from using the PKCS #8 format for
// export since an exception is thrown when checking for JWK support.
// Therefore, just return false so that the user is not blocked.
return false;
}
}

Expand Down
27 changes: 24 additions & 3 deletions kse/src/main/java/org/kse/crypto/signing/BcEd25519Signer.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,20 @@
*/
package org.kse.crypto.signing;

import java.io.IOException;
import java.security.PrivateKey;
import java.util.Set;

import org.bouncycastle.crypto.params.Ed25519PrivateKeyParameters;
import org.bouncycastle.crypto.signers.Ed25519Signer;
import org.bouncycastle.crypto.util.PrivateKeyFactory;

import com.nimbusds.jose.JOSEException;
import com.nimbusds.jose.JWSAlgorithm;
import com.nimbusds.jose.JWSHeader;
import com.nimbusds.jose.JWSSigner;
import com.nimbusds.jose.crypto.impl.BaseJWSProvider;
import com.nimbusds.jose.jwk.Curve;
import com.nimbusds.jose.jwk.OctetKeyPair;
import com.nimbusds.jose.util.Base64URL;

Expand All @@ -41,12 +45,29 @@ public class BcEd25519Signer extends BaseJWSProvider implements JWSSigner {

private final Ed25519PrivateKeyParameters privateKeyParams;

public BcEd25519Signer(OctetKeyPair privateKey) throws JOSEException {
/**
* Creates a new BcEd25519Signer.
*
* @param privateKey The private key for signing.
* @throws IOException
* @throws JOSEException
*/
public BcEd25519Signer(PrivateKey privateKey) throws IOException, JOSEException {
super(SUPPORTED);
if (!privateKey.isPrivate()) {

var params = (Ed25519PrivateKeyParameters) PrivateKeyFactory.createKey(privateKey.getEncoded());
OctetKeyPair okp = buildOctectKeyAPair(params);

if (!okp.isPrivate()) {
throw new JOSEException("OctetKeyPair must contain a private key (d)");
}
privateKeyParams = new Ed25519PrivateKeyParameters(privateKey.getDecodedD(), 0);
privateKeyParams = new Ed25519PrivateKeyParameters(okp.getDecodedD(), 0);
}

private OctetKeyPair buildOctectKeyAPair(Ed25519PrivateKeyParameters params) {
Base64URL base64EncodedPubKey = Base64URL.encode(params.generatePublicKey().getEncoded());
Base64URL base64EncodedParams = Base64URL.encode(params.getEncoded());
return new OctetKeyPair.Builder(Curve.Ed25519, base64EncodedPubKey).d(base64EncodedParams).build();
}

@Override
Expand Down
14 changes: 12 additions & 2 deletions kse/src/main/java/org/kse/crypto/signing/BcEd25519Verifier.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,14 @@

import org.bouncycastle.crypto.params.Ed25519PublicKeyParameters;
import org.bouncycastle.crypto.signers.Ed25519Signer;
import org.bouncycastle.jcajce.interfaces.EdDSAPublicKey;

import com.nimbusds.jose.JOSEException;
import com.nimbusds.jose.JWSAlgorithm;
import com.nimbusds.jose.JWSHeader;
import com.nimbusds.jose.JWSVerifier;
import com.nimbusds.jose.crypto.impl.BaseJWSProvider;
import com.nimbusds.jose.jwk.Curve;
import com.nimbusds.jose.jwk.OctetKeyPair;
import com.nimbusds.jose.util.Base64URL;

Expand All @@ -41,9 +43,17 @@ public class BcEd25519Verifier extends BaseJWSProvider implements JWSVerifier {

private final Ed25519PublicKeyParameters publicKeyParams;

public BcEd25519Verifier(OctetKeyPair publicKey) throws JOSEException {
/**
* Creates a new BcEd25519Verifier.
*
* @param publicKey The public key to use for verifying a signature.
*/
public BcEd25519Verifier(EdDSAPublicKey publicKey) {
super(SUPPORTED);
publicKeyParams = new Ed25519PublicKeyParameters(publicKey.getDecodedX(), 0);

OctetKeyPair okp = new OctetKeyPair.Builder(Curve.Ed448,
Base64URL.encode(publicKey.getPointEncoding())).build();
publicKeyParams = new Ed25519PublicKeyParameters(okp.getDecodedX(), 0);
}

@Override
Expand Down
25 changes: 22 additions & 3 deletions kse/src/main/java/org/kse/crypto/signing/BcEd448Signer.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,20 @@
*/
package org.kse.crypto.signing;

import java.io.IOException;
import java.security.PrivateKey;
import java.util.Set;

import org.bouncycastle.crypto.params.Ed448PrivateKeyParameters;
import org.bouncycastle.crypto.signers.Ed448Signer;
import org.bouncycastle.crypto.util.PrivateKeyFactory;

import com.nimbusds.jose.JOSEException;
import com.nimbusds.jose.JWSAlgorithm;
import com.nimbusds.jose.JWSHeader;
import com.nimbusds.jose.JWSSigner;
import com.nimbusds.jose.crypto.impl.BaseJWSProvider;
import com.nimbusds.jose.jwk.Curve;
import com.nimbusds.jose.jwk.OctetKeyPair;
import com.nimbusds.jose.util.Base64URL;

Expand All @@ -42,12 +46,27 @@ public class BcEd448Signer extends BaseJWSProvider implements JWSSigner {

private final Ed448PrivateKeyParameters privateKeyParams;

public BcEd448Signer(OctetKeyPair privateKey) throws JOSEException {
/**
* Creates a new BcEd448Signer.
*
* @param privateKey The private key for signing.
* @throws IOException
* @throws JOSEException
*/
public BcEd448Signer(PrivateKey privateKey) throws IOException, JOSEException {
super(SUPPORTED);
if (!privateKey.isPrivate()) {
var params = (Ed448PrivateKeyParameters) PrivateKeyFactory.createKey(privateKey.getEncoded());
OctetKeyPair okp = buildOctectKeyAPair(params);
if (!okp.isPrivate()) {
throw new JOSEException("OctetKeyPair must contain a private key (d)");
}
privateKeyParams = new Ed448PrivateKeyParameters(privateKey.getDecodedD(), 0);
privateKeyParams = new Ed448PrivateKeyParameters(okp.getDecodedD(), 0);
}

private OctetKeyPair buildOctectKeyAPair(Ed448PrivateKeyParameters params) {
Base64URL base64EncodedPubKey = Base64URL.encode(params.generatePublicKey().getEncoded());
Base64URL base64EncodedParams = Base64URL.encode(params.getEncoded());
return new OctetKeyPair.Builder(Curve.Ed448, base64EncodedPubKey).d(base64EncodedParams).build();
}

@Override
Expand Down
14 changes: 12 additions & 2 deletions kse/src/main/java/org/kse/crypto/signing/BcEd448Verifier.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,14 @@

import org.bouncycastle.crypto.params.Ed448PublicKeyParameters;
import org.bouncycastle.crypto.signers.Ed448Signer;
import org.bouncycastle.jcajce.interfaces.EdDSAPublicKey;

import com.nimbusds.jose.JOSEException;
import com.nimbusds.jose.JWSAlgorithm;
import com.nimbusds.jose.JWSHeader;
import com.nimbusds.jose.JWSVerifier;
import com.nimbusds.jose.crypto.impl.BaseJWSProvider;
import com.nimbusds.jose.jwk.Curve;
import com.nimbusds.jose.jwk.OctetKeyPair;
import com.nimbusds.jose.util.Base64URL;

Expand All @@ -42,9 +44,17 @@ public class BcEd448Verifier extends BaseJWSProvider implements JWSVerifier {

private final Ed448PublicKeyParameters publicKeyParams;

public BcEd448Verifier(OctetKeyPair publicKey) throws JOSEException {
/**
* Creates a new BcEd448Verifier.
*
* @param publicKey The public key to use for verifying a signature.
*/
public BcEd448Verifier(EdDSAPublicKey publicKey) {
super(SUPPORTED);
publicKeyParams = new Ed448PublicKeyParameters(publicKey.getDecodedX(), 0);

OctetKeyPair okp = new OctetKeyPair.Builder(Curve.Ed25519,
Base64URL.encode(publicKey.getPointEncoding())).build();
publicKeyParams = new Ed448PublicKeyParameters(okp.getDecodedX(), 0);
}

@Override
Expand Down
40 changes: 4 additions & 36 deletions kse/src/main/java/org/kse/crypto/signing/JwsSigner.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,25 +20,17 @@

package org.kse.crypto.signing;

import java.io.IOException;
import java.security.PrivateKey;
import java.security.Provider;
import java.security.interfaces.EdECPrivateKey;

import org.bouncycastle.crypto.params.Ed25519PrivateKeyParameters;
import org.bouncycastle.crypto.params.Ed448PrivateKeyParameters;
import org.bouncycastle.crypto.util.PrivateKeyFactory;
import org.kse.crypto.ecc.EdDSACurves;

import com.nimbusds.jose.JOSEException;
import com.nimbusds.jose.JWSAlgorithm;
import com.nimbusds.jose.JWSHeader;
import com.nimbusds.jose.JWSSigner;
import com.nimbusds.jose.crypto.ECDSASigner;
import com.nimbusds.jose.crypto.RSASSASigner;
import com.nimbusds.jose.jwk.Curve;
import com.nimbusds.jose.jwk.OctetKeyPair;
import com.nimbusds.jose.util.Base64URL;
import com.nimbusds.jwt.JWTClaimsSet;
import com.nimbusds.jwt.SignedJWT;

Expand Down Expand Up @@ -70,14 +62,14 @@ public static SignedJWT signJwt(JWSAlgorithm signatureAlgorithm, com.nimbusds.jo
} else if (JWSAlgorithm.Family.EC.contains(signatureAlgorithm)) {
signer = new ECDSASigner(privateKey, curve);
} else if (JWSAlgorithm.Ed25519 == signatureAlgorithm) {
signer = newEd25519Signer(privateKey);
signer = new BcEd25519Signer(privateKey);
} else if (JWSAlgorithm.Ed448 == signatureAlgorithm) {
signer = newEd448Signer(privateKey);
signer = new BcEd448Signer(privateKey);
} else if (JWSAlgorithm.EdDSA == signatureAlgorithm) {
if (EdDSACurves.ED448.jce().equals(((EdECPrivateKey) privateKey).getParams().getName())) {
signer = newEd448Signer(privateKey);
signer = new BcEd448Signer(privateKey);
} else {
signer = newEd25519Signer(privateKey);
signer = new BcEd25519Signer(privateKey);
}
}

Expand All @@ -90,28 +82,4 @@ public static SignedJWT signJwt(JWSAlgorithm signatureAlgorithm, com.nimbusds.jo

return signedJWT;
}

private static JWSSigner newEd25519Signer(PrivateKey privateKey) throws IOException, JOSEException {
var params = (Ed25519PrivateKeyParameters) PrivateKeyFactory.createKey(privateKey.getEncoded());
OctetKeyPair okp = buildOctectKeyAPair(params);
return new BcEd25519Signer(okp);
}

private static JWSSigner newEd448Signer(PrivateKey privateKey) throws IOException, JOSEException {
var params = (Ed448PrivateKeyParameters) PrivateKeyFactory.createKey(privateKey.getEncoded());
OctetKeyPair okp = buildOctectKeyAPair(params);
return new BcEd448Signer(okp);
}

private static OctetKeyPair buildOctectKeyAPair(Ed25519PrivateKeyParameters params) {
Base64URL base64EncodedPubKey = Base64URL.encode(params.generatePublicKey().getEncoded());
Base64URL base64EncodedParams = Base64URL.encode(params.getEncoded());
return new OctetKeyPair.Builder(Curve.Ed25519, base64EncodedPubKey).d(base64EncodedParams).build();
}

private static OctetKeyPair buildOctectKeyAPair(Ed448PrivateKeyParameters params) {
Base64URL base64EncodedPubKey = Base64URL.encode(params.generatePublicKey().getEncoded());
Base64URL base64EncodedParams = Base64URL.encode(params.getEncoded());
return new OctetKeyPair.Builder(Curve.Ed448, base64EncodedPubKey).d(base64EncodedParams).build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,7 @@ protected void doAction() {

PublicKey publicKey = getPublicKey(alias);

boolean isKeyExportableAsJWK = JwkUtil.isPublicKeyTypeExportable(publicKey);

DExportPublicKey dExportPublicKey = new DExportPublicKey(frame, alias, isKeyExportableAsJWK);
DExportPublicKey dExportPublicKey = new DExportPublicKey(frame, alias, publicKey);
dExportPublicKey.setLocationRelativeTo(frame);
dExportPublicKey.setVisible(true);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,7 @@ protected void doAction() {

PublicKey publicKey = getPublicKey(alias);

boolean isKeyExportableAsJWK = JwkUtil.isPublicKeyTypeExportable(publicKey);

DExportPublicKey dExportPublicKey = new DExportPublicKey(frame, alias, isKeyExportableAsJWK);
DExportPublicKey dExportPublicKey = new DExportPublicKey(frame, alias, publicKey);
dExportPublicKey.setLocationRelativeTo(frame);
dExportPublicKey.setVisible(true);

Expand Down
16 changes: 4 additions & 12 deletions kse/src/main/java/org/kse/gui/dialogs/DViewJwt.java
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@
import org.kse.crypto.filetype.CryptoFileType;
import org.kse.crypto.filetype.CryptoFileUtil;
import org.kse.crypto.publickey.OpenSslPubUtil;
import org.kse.crypto.signing.BcEd25519Verifier;
import org.kse.crypto.signing.BcEd448Verifier;
import org.kse.gui.CursorUtil;
import org.kse.gui.LnfUtil;
import org.kse.gui.PlatformUtil;
Expand All @@ -69,13 +71,7 @@
import com.nimbusds.jose.JWSVerifier;
import com.nimbusds.jose.Payload;
import com.nimbusds.jose.crypto.ECDSAVerifier;
import org.kse.crypto.signing.BcEd25519Verifier;
import org.kse.crypto.signing.BcEd448Verifier;

import com.nimbusds.jose.crypto.RSASSAVerifier;
import com.nimbusds.jose.jwk.Curve;
import com.nimbusds.jose.jwk.OctetKeyPair;
import com.nimbusds.jose.util.Base64URL;
import com.nimbusds.jwt.JWT;
import com.nimbusds.jwt.JWTParser;
import com.nimbusds.jwt.SignedJWT;
Expand Down Expand Up @@ -314,13 +310,9 @@ private void verifyPressed() {
// Works for Java 15+ since OpenSslPubUtil uses the BC provider for loading the key
} else if (publicKey instanceof EdDSAPublicKey) {
if (EdDSACurves.ED448.jce().equals(publicKey.getAlgorithm())) {
OctetKeyPair okp = new OctetKeyPair.Builder(Curve.Ed448,
Base64URL.encode(((EdDSAPublicKey) publicKey).getPointEncoding())).build();
verifier = new BcEd448Verifier(okp);
verifier = new BcEd448Verifier((EdDSAPublicKey) publicKey);
} else {
OctetKeyPair okp = new OctetKeyPair.Builder(Curve.Ed25519,
Base64URL.encode(((EdDSAPublicKey) publicKey).getPointEncoding())).build();
verifier = new BcEd25519Verifier(okp);
verifier = new BcEd25519Verifier((EdDSAPublicKey) publicKey);
}
} else {
JOptionPane.showMessageDialog(this, res.getString("DViewJwt.InvalidPublicKey.message"),
Expand Down
4 changes: 1 addition & 3 deletions kse/src/main/java/org/kse/gui/dialogs/DViewPublicKey.java
Original file line number Diff line number Diff line change
Expand Up @@ -310,9 +310,7 @@ private void exportPressed() {
File exportFile = null;

try {
boolean isKeyExportableAsJWK = JwkUtil.isPublicKeyTypeExportable(publicKey);

DExportPublicKey dExportPublicKey = new DExportPublicKey((Window) getParent(), alias, isKeyExportableAsJWK);
DExportPublicKey dExportPublicKey = new DExportPublicKey((Window) getParent(), alias, publicKey);
dExportPublicKey.setLocationRelativeTo(this);
dExportPublicKey.setVisible(true);

Expand Down
Loading
Loading