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

Instantiate RSASignatureGenerator and RSASignatureValidator with in m… (CADC-12974) #236

Merged
merged 3 commits into from
Dec 13, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
2 changes: 1 addition & 1 deletion cadc-util/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ sourceCompatibility = 1.8

group = 'org.opencadc'

version = '1.10.2'
version = '1.10.3'

description = 'OpenCADC core utility library'
def git_url = 'https://github.com/opencadc/core'
Expand Down
98 changes: 52 additions & 46 deletions cadc-util/src/main/java/ca/nrc/cadc/util/RsaSignatureGenerator.java
Original file line number Diff line number Diff line change
Expand Up @@ -96,12 +96,10 @@
* This class is used to sign and/or verify signed messages. The class requires
* and RSA private key to sign a message.
*
* <p>The key is passed to the class via the MessageRSA.keys file in the
* classpath. This class cannot be instantiated without this file containing
* a private RSA key.
* <p>The key is passed to the class via a file or as a binary array.
*
* <p>Format of the key:
* The private key in the MessageRSA.keys file must be in PEM TKCS#8 to work
* The private key in the MessageRSA.keys file must be in PEM TKCS#8 to work
* with basic Java. These keys are in text format delimited by the following
* rows:
* "-----BEGIN PRIVATE KEY-----" and "-----END PRIVATE KEY-----".
Expand Down Expand Up @@ -150,86 +148,94 @@ public RsaSignatureGenerator(File keyFile) {
super(keyFile, true);
initPrivateKey(keyFile);
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think RsaSignatureGenerator needs a method like

public static KeyPair generateKeyPair(int len)

It's essentially the first half of the current generateKeyPair(File, File, int) method. The code in raven and vault can generate in-memory keys when necessary; cavern needs the existing File based method. I'm assuming byte correct byte[] is available via KeyPair methods (looks like it).

public RsaSignatureGenerator(byte[] keyContent) {
super(keyContent, true);
initPrivateKey(keyContent);
}

private void initPrivateKey(File keysFile) {

KeyFactory keyFactory = null;
try {
keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
} catch (NoSuchAlgorithmException e1) {
throw new RuntimeException("BUG: Wrong algorithm " + KEY_ALGORITHM,
e1);
}
// try to load the keys
try {
BufferedReader br = new BufferedReader(new FileReader(keysFile));
try {
try (BufferedReader br = new BufferedReader(new FileReader(keysFile))) {
StringBuilder sb = null;
boolean read = false;
String line = null;
while ((line = br.readLine()) != null) {
if (line.equalsIgnoreCase(PRIV_KEY_START)) {
if (read) {
throw new
IllegalArgumentException("Corrupted keys file");
throw new
IllegalArgumentException("Corrupted keys file");
}

if (privKey != null) {
throw new
IllegalStateException("Found two private keys");
IllegalStateException("Found two private keys");
}

read = true;
sb = new StringBuilder();
continue;
}

if (line.equalsIgnoreCase(PRIV_KEY_END)) {
if (!read) {
throw new
IllegalArgumentException("Corrupted keys file");
throw new
IllegalArgumentException("Corrupted keys file");
}

read = false;
String payload = sb.toString();
byte[] bytes = Base64.decode(payload);
PKCS8EncodedKeySpec privateKeySpec = new
PKCS8EncodedKeySpec(bytes);
try {
privKey =
keyFactory.generatePrivate(privateKeySpec);
// get corresponding public key
RSAPrivateCrtKey privk =
(RSAPrivateCrtKey)privKey;
RSAPublicKeySpec publicKeySpec =
new java.security.spec.RSAPublicKeySpec(
privk.getModulus(),
privk.getPublicExponent());

PublicKey publicKey =
keyFactory.generatePublic(publicKeySpec);
pubKeys.add(publicKey);
} catch (InvalidKeySpecException e) {
log.warn("Could not parse private key", e);
}
initPrivateKey(bytes);
}

if (read) {
sb.append(line);
}
}
} finally {
br.close();
}
} catch (IOException e) {
String msg = "Could not read keys";
throw new RuntimeException(msg, e);
}

if (privKey == null) {
String msg = "No valid private key found";
throw new IllegalStateException(msg);
}
}
}

private void initPrivateKey(byte[] keysContent) {

KeyFactory keyFactory = null;
try {
keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
} catch (NoSuchAlgorithmException e1) {
throw new RuntimeException("BUG: Wrong algorithm " + KEY_ALGORITHM,
e1);
}

PKCS8EncodedKeySpec privateKeySpec = new
PKCS8EncodedKeySpec(keysContent);
try {
privKey =
keyFactory.generatePrivate(privateKeySpec);
// get corresponding public key
RSAPrivateCrtKey privk =
(RSAPrivateCrtKey)privKey;
RSAPublicKeySpec publicKeySpec =
new java.security.spec.RSAPublicKeySpec(
privk.getModulus(),
privk.getPublicExponent());

PublicKey publicKey =
keyFactory.generatePublic(publicKeySpec);
pubKeys.add(publicKey);
} catch (InvalidKeySpecException e) {
log.warn("Could not parse private key", e);
}
}

/**
Expand Down
81 changes: 46 additions & 35 deletions cadc-util/src/main/java/ca/nrc/cadc/util/RsaSignatureVerifier.java
Original file line number Diff line number Diff line change
Expand Up @@ -92,9 +92,7 @@
* This class is used to verify signed messages. The class requires
* an RSA public key to verify a message.
*
* <p>The keys are passed to the class via the RsaSignaturePub.key file in the
* classpath. This class cannot be instantiated without this file containing
* public RSA keys.
* <p>The keys are passed to the class via a file or as a binary array.
*
* <p>Format of the keys:
* Public keys in the keys file must be in PEM TKCS#1These keys are
Expand Down Expand Up @@ -135,18 +133,18 @@ public class RsaSignatureVerifier {
public static final String PUB_KEY_START = "-----BEGIN PUBLIC KEY-----";
public static final String PUB_KEY_END = "-----END PUBLIC KEY-----";


/**
* Default constructor. This will look for a key file named RsaSignaturePub.key
* and use it to verify.
*
*
* @deprecated use RsaSignatureVerifier(File keyFile)
*/
@Deprecated
public RsaSignatureVerifier() {
this(PUB_KEY_FILE_NAME);
}

/**
* Constructor.
*
Expand All @@ -165,6 +163,15 @@ public RsaSignatureVerifier(File keyFile) {
}
init(keyFile);
}

public RsaSignatureVerifier(byte[] keyContent) {
init(keyContent);
}

public RsaSignatureVerifier(byte[] keyContent, boolean isPrivateKey) {
andamian marked this conversation as resolved.
Show resolved Hide resolved
if(!isPrivateKey)
init(keyContent);
}

// ctors for use by RsaSignatureGenerator subclass
@Deprecated
Expand All @@ -183,7 +190,7 @@ protected RsaSignatureVerifier(File keyFile, boolean isPrivateKeyFile) {
init(keyFile);
}
}

protected final File findFile(String fname) throws MissingResourceException {
File ret = new File(DEFAULT_CONFIG_DIR, fname);
if (!ret.exists()) {
Expand All @@ -198,68 +205,72 @@ protected final File findFile(String fname) throws MissingResourceException {
* @param keysFile
*/
protected void init(File keysFile) {
KeyFactory keyFactory = null;
try {
keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
} catch (NoSuchAlgorithmException e1) {
throw new RuntimeException("BUG: Wrong algorithm " + KEY_ALGORITHM, e1);
}
// try to load the keys
try {
log.debug("read pub keys: " + keysFile);
BufferedReader br = new BufferedReader(new
FileReader(keysFile));
try {
try (BufferedReader br = new BufferedReader(new
FileReader(keysFile))) {
StringBuilder sb = null;
boolean readPub = false;
String line = null;
String line;
while ((line = br.readLine()) != null) {
if (line.equalsIgnoreCase(PUB_KEY_START)) {
if (readPub) {
throw new
IllegalArgumentException("Corrupted keys file");
throw new
IllegalArgumentException("Corrupted keys file");
}

readPub = true;
sb = new StringBuilder();
continue;
}

if (line.equalsIgnoreCase(PUB_KEY_END)) {
if (!readPub) {
throw new
IllegalArgumentException("Corrupted keys file");
throw new
IllegalArgumentException("Corrupted keys file");
}

readPub = false;
String payload = sb.toString();
byte[] bytes = Base64.decode(payload);
X509EncodedKeySpec publicKeySpec =
new X509EncodedKeySpec(bytes);
try {
pubKeys.add(keyFactory.generatePublic(publicKeySpec));
} catch (InvalidKeySpecException e) {
log.warn("Could not parse public key", e);
}
init(bytes);
}
if (readPub) {
sb.append(line);
}
}
} finally {
br.close();
}
} catch (IOException e) {
String msg = "Could not read keys";
throw new RuntimeException(msg, e);
}

if (pubKeys.isEmpty()) {
String msg = "No valid public keys found";
throw new IllegalStateException(msg);
}
}
}

/**
* Init public keys from binary content.
*
* @param keysContent
*/
protected void init(byte[] keysContent) {
KeyFactory keyFactory = null;
try {
keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
} catch (NoSuchAlgorithmException e1) {
throw new RuntimeException("BUG: Wrong algorithm " + KEY_ALGORITHM, e1);
}

X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(keysContent);
try {
pubKeys.add(keyFactory.generatePublic(publicKeySpec));
} catch (InvalidKeySpecException e) {
log.warn("Could not parse public key", e);
}
}

/**
* Method use to verify a stream
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@
import java.io.File;
import java.io.FileOutputStream;
import java.io.PrintWriter;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.util.Date;
import java.util.MissingResourceException;
import org.apache.log4j.Level;
Expand Down Expand Up @@ -77,6 +80,30 @@ public void testSignVerify() throws Exception {
}
}

@Test
public void testSignVerifyBytes() throws Exception {
final String testString = "cadcauthtest1-" + new Date();
andamian marked this conversation as resolved.
Show resolved Hide resolved
KeyPairGenerator kpg;
try {
kpg = KeyPairGenerator.getInstance(RsaSignatureVerifier.KEY_ALGORITHM);
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(
"BUG: illegal key algorithm - " + RsaSignatureVerifier.KEY_ALGORITHM, e);
}
int[] keyLengths = { 512, 1024, 2048, 4096 };
for (int len : keyLengths) {
log.info("testSignVerifyBytes: " + len);

kpg.initialize(len);
KeyPair keyPair = kpg.genKeyPair();
RsaSignatureGenerator sg = new RsaSignatureGenerator(keyPair.getPrivate().getEncoded());
RsaSignatureVerifier sv = new RsaSignatureVerifier(keyPair.getPublic().getEncoded());
assertTrue("Signature does not work!!!!",
sv.verify(new ByteArrayInputStream(testString.getBytes()),
sg.sign(new ByteArrayInputStream(testString.getBytes()))));
}
}

@Test
public void testKeyFileNotFound() throws Exception {
final String testString = "cadcauthtest1-" + new Date();
Expand Down
Loading