Skip to content

Commit

Permalink
fix vt-middleware#69-ssh-pubkey-pem
Browse files Browse the repository at this point in the history
  • Loading branch information
Erdem A Memisyazici committed Mar 27, 2024
1 parent e49bc14 commit 38c43b1
Show file tree
Hide file tree
Showing 14 changed files with 1,039 additions and 35 deletions.
26 changes: 26 additions & 0 deletions src/main/java/org/cryptacular/KeyDecoder.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/* See LICENSE for licensing and NOTICE for copyright. */
package org.cryptacular;

/**
* Contract interface for converting encoded bytes to an object.
*
* @param <T> Type of object to produce on decode.
*
* @author Middleware Services
*/
public interface KeyDecoder<T>
{

/**
* Produces an object from an encoded representation.
*
* @param encoded data.
* @param args Additional data required to perform decoding.
*
* @return Decoded object.
*
* @throws EncodingException on encoding errors.
*/
T decode(byte[] encoded, Object... args) throws EncodingException;

}
16 changes: 2 additions & 14 deletions src/main/java/org/cryptacular/asn/ASN1Decoder.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/* See LICENSE for licensing and NOTICE for copyright. */
package org.cryptacular.asn;

import org.cryptacular.EncodingException;
import org.cryptacular.KeyDecoder;

/**
* Strategy interface for converting encoded ASN.1 bytes to an object.
Expand All @@ -10,18 +10,6 @@
*
* @author Middleware Services
*/
public interface ASN1Decoder<T>
public interface ASN1Decoder<T> extends KeyDecoder<T>
{

/**
* Produces an object from an encoded representation.
*
* @param encoded ASN.1 encoded data.
* @param args Additional data required to perform decoding.
*
* @return Decoded object.
*
* @throws EncodingException on encoding errors.
*/
T decode(byte[] encoded, Object... args) throws EncodingException;
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters;
import org.bouncycastle.jcajce.provider.asymmetric.util.ECUtil;
import org.cryptacular.EncodingException;
import org.cryptacular.io.pem.PemObject;
import org.cryptacular.pbe.OpenSSLAlgorithm;
import org.cryptacular.pbe.OpenSSLEncryptionScheme;
import org.cryptacular.util.ByteUtil;
Expand All @@ -36,7 +37,7 @@ public class OpenSSLPrivateKeyDecoder extends AbstractPrivateKeyDecoder<Asymmetr
protected byte[] decryptKey(final byte[] encrypted, final char[] password)
{
final String pem = new String(encrypted, ByteUtil.ASCII_CHARSET);
final int start = pem.indexOf(PemUtil.DEK_INFO);
final int start = pem.indexOf(PemObject.RFC1421_HEADER_FIELD_DEK_INFO);
final int eol = pem.indexOf('\n', start);
final String[] dekInfo = pem.substring(start + 10, eol).split(",");
final String alg = dekInfo[0];
Expand Down
42 changes: 41 additions & 1 deletion src/main/java/org/cryptacular/asn/PublicKeyDecoder.java
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
/* See LICENSE for licensing and NOTICE for copyright. */
package org.cryptacular.asn;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import org.bouncycastle.asn1.ASN1InputStream;
import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
import org.bouncycastle.crypto.util.PublicKeyFactory;
import org.cryptacular.EncodingException;
import org.cryptacular.io.pem.PemFormat;
import org.cryptacular.io.pem.PemObject;
import org.cryptacular.ssh.SSHPublicKeyDecoder;
import org.cryptacular.util.ByteUtil;
import org.cryptacular.util.PemUtil;

/**
Expand All @@ -21,11 +28,44 @@ public AsymmetricKeyParameter decode(final byte[] encoded, final Object... args)
{
try {
if (PemUtil.isPem(encoded)) {
return PublicKeyFactory.createKey(PemUtil.decode(encoded));
return decodePem(encoded, args);
} else if (SSHPublicKeyDecoder.isRFC4253EncodedPublicKey(encoded)) {
return new SSHPublicKeyDecoder().decode(new String(encoded, ByteUtil.ASCII_CHARSET));
}
return PublicKeyFactory.createKey(new ASN1InputStream(encoded).readObject().getEncoded());
} catch (IOException e) {
throw new EncodingException("ASN.1 decoding error", e);
}
}


/**
* Decodes PEM formats.
*
* @param encoded data.
* @param args Additional data required to perform decoding.
*
* @return Decoded object.
*
* @throws EncodingException on encoding errors.
*/
private AsymmetricKeyParameter decodePem(final byte[] encoded, final Object... args)
throws EncodingException
{
final PemObject pem;
try {
pem = PemUtil.read(new BufferedReader(
new InputStreamReader(new ByteArrayInputStream(encoded))));
} catch (IllegalArgumentException | IOException ex) {
throw new EncodingException("Could not parse PEM data", ex);
}
if (PemFormat.RFC4716.equals(pem.getDescriptor().getPemFormat())) {
return new SSHPublicKeyDecoder().decode(pem.getContent(), args);
}
try {
return PublicKeyFactory.createKey(pem.getContent());
} catch (IOException ex) {
throw new EncodingException("Could not decode key", ex);
}
}
}
27 changes: 27 additions & 0 deletions src/main/java/org/cryptacular/io/pem/PemFormat.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/* See LICENSE for licensing and NOTICE for copyright. */
package org.cryptacular.io.pem;

/**
* Enum to define the RFC governing the PEM format
*
* @author Middleware Services
*/
public enum PemFormat
{
/**
* a PEM encoded file as defined by RFC-2440 (OpenPGP).
*/
RFC2440,
/**
* a PEM encoded file as defined by RFC-7468 (Textual Encodings of PKIX, PKCS, and CMS Structures).
*/
RFC7468,
/**
* a PEM encoded file as defined by RFC-1421 (Privacy Enhanced Message).
*/
RFC1421,
/**
* a PEM encoded file as defined by RFC-4716 (SSH).
*/
RFC4716,
}
Loading

0 comments on commit 38c43b1

Please sign in to comment.