Implement support for PKCS1 in CredentialParser class.

This commit is contained in:
chubtub 2020-03-26 13:42:31 -04:00
parent 0c57e58c46
commit 2108d902a4
4 changed files with 52 additions and 94 deletions

View File

@ -1,6 +1,10 @@
package hirs.swid;
import org.bouncycastle.cert.jcajce.JcaX509ExtensionUtils;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.openssl.PEMKeyPair;
import org.bouncycastle.openssl.PEMParser;
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
import org.bouncycastle.util.encoders.Base64;
import java.io.*;
@ -11,10 +15,17 @@ import java.security.cert.X509Certificate;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
/**
* This class parses private key, public key, and certificate for use in their respective java.security objects.
*/
public class CredentialParser {
private static final String X509 = "X.509";
private static final String JKS = "JKS";
private static final String PEM = "PEM";
private static final String PKCS1_HEADER = "-----BEGIN RSA PRIVATE KEY-----";
private static final String PKCS1_FOOTER = "-----END RSA PRIVATE KEY-----";
private static final String PKCS8_HEADER = "-----BEGIN PRIVATE KEY-----";
private static final String PKCS8_FOOTER = "-----END PRIVATE KEY-----";
private X509Certificate certificate;
private PrivateKey privateKey;
private PublicKey publicKey;
@ -79,6 +90,9 @@ public class CredentialParser {
/**
* This method extracts the private key from a PEM file.
* Both PKCS1 and PKCS8 formats are handled.
* Algorithm argument is present to allow handling of multiple encryption algorithms,
* but for now it is always RSA.
* @param filename
* @return
*/
@ -93,15 +107,18 @@ public class CredentialParser {
dis.close();
String privateKeyStr = new String(key);
privateKeyStr = privateKeyStr.replace("-----BEGIN PRIVATE KEY-----\n", "");
privateKeyStr = privateKeyStr.replace("-----END PRIVATE KEY-----", "");
if (privateKeyStr.contains(PKCS1_HEADER)) {
privateKey = getPKCS1KeyPair(filename).getPrivate();
} else if (privateKeyStr.contains(PKCS8_HEADER)) {
privateKeyStr = privateKeyStr.replace(PKCS8_HEADER, "");
privateKeyStr = privateKeyStr.replace(PKCS8_FOOTER, "");
Base64 base64 = new Base64();
byte[] decodedKey = base64.decode(privateKeyStr);
PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(decodedKey);
KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
byte[] decodedKey = Base64.decode(privateKeyStr);
PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(decodedKey);
KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
privateKey = keyFactory.generatePrivate(spec);
privateKey = keyFactory.generatePrivate(spec);
}
} catch (FileNotFoundException e) {
System.out.println("Unable to locate private key file: " + filename);
} catch (NoSuchAlgorithmException e) {
@ -116,7 +133,21 @@ public class CredentialParser {
}
/**
* This method returns the private key in a JKS keystore.
* This method reads a PKCS1 keypair from a PEM file.
* @param filename
* @return
*/
private KeyPair getPKCS1KeyPair(String filename) throws IOException {
Security.addProvider(new BouncyCastleProvider());
PEMParser pemParser = new PEMParser(new FileReader(filename));
JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider("BC");
KeyPair keyPair = converter.getKeyPair((PEMKeyPair) pemParser.readObject());
return keyPair;
}
/**
* This method returns the private key from a JKS keystore.
* @param keystoreFile
* @param alias
* @param password

View File

@ -20,15 +20,10 @@ public class SwidTagConstants {
public static final String SIGNATURE_ALGORITHM_RSA_SHA256 = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256";
public static final String SCHEMA_STATEMENT = "ISO/IEC 19770-2:2015 Schema (XSD 1.0) "
+ "- September 2015, see http://standards.iso.org/iso/19770/-2/2015/schema.xsd";
public static final String SCHEMA_PACKAGE = "hirs.swid.xjc";
public static final String SCHEMA_LANGUAGE = XMLConstants.W3C_XML_SCHEMA_NS_URI;
public static final String SCHEMA_URL = "swid_schema.xsd";
public static final String HIRS_SWIDTAG_HEADERS = "hirsSwidTagHeader.properties";
public static final String EXAMPLE_PROPERTIES = "swidExample.properties";
public static final String SOFTWARE_IDENTITY = "SoftwareIdentity";
public static final String ENTITY = "Entity";
public static final String LINK = "Link";
@ -148,49 +143,4 @@ public class SwidTagConstants {
"pathSeparator", "n8060");
public static final String CERTIFICATE_SUBJECT_KEY_IDENTIFIER = "2.5.29.14";
//Below properties can probably be deleted
public static final String SOFTWARE_IDENTITY_NAME = "softwareIdentity.name";
public static final String SOFTWARE_IDENTITY_TAGID = "softwareIdentity.tagId";
public static final String SOFTWARE_IDENTITY_VERSION = "softwareIdentity.version";
public static final String SOFTWARE_IDENTITY_CORPUS = "softwareIdentity.corpus";
public static final String SOFTWARE_IDENTITY_PATCH = "softwareIdentity.patch";
public static final String SOFTWARE_IDENTITY_SUPPLEMENTAL = "softwareIdentity.supplemental";
public static final String ENTITY_NAME = "entity.name";
public static final String ENTITY_REGID = "entity.regid";
public static final String ENTITY_ROLE = "entity.role";
public static final String ENTITY_THUMBPRINT = "entity.thumbprint";
public static final String LINK_HREF = "link.href";
public static final String LINK_REL = "link.rel";
public static final String META_PCURILOCAL = "softwareMeta.pcUriLocal";
public static final String META_BINDINGSPEC = "softwareMeta.bindingSpec";
public static final String META_BINDINGSPECVERSION = "softwareMeta.bindingSpecVersion";
public static final String META_PLATFORMMANUFACTURERID = "softwareMeta.platformManufacturerId";
public static final String META_PLATFORMMANUFACTURERSTR = "softwareMeta.platformManufacturerStr";
public static final String META_PLATFORMMODEL = "softwareMeta.platformModel";
public static final String META_COMPONENTCLASS = "softwareMeta.componentClass";
public static final String META_COMPONENTMANUFACTURER = "softwareMeta.componentManufacturer";
public static final String META_COMPONENTMANUFACTURERID = "softwareMeta.componentManufacturerId";
public static final String META_RIMLINKHASH = "softwareMeta.rimLinkHash";
public static final String PAYLOAD_ENVVARPREFIX = "n8060.envvarprefix";
public static final String PAYLOAD_ENVVARSUFFIX = "n8060.envvarsuffix";
public static final String PAYLOAD_PATHSEPARATOR = "n8060.pathseparator";
public static final String DIRECTORY_KEY = "directory.key";
public static final String DIRECTORY_LOCATION = "directory.location";
public static final String DIRECTORY_NAME = "directory.name";
public static final String DIRECTORY_ROOT = "directory.root";
public static final String FILE_KEY = "file.key";
public static final String FILE_LOCATION = "file.location";
public static final String FILE_NAME = "file.name";
public static final String FILE_ROOT = "file.root";
public static final String FILE_SIZE = "file.size";
public static final String FILE_VERSION = "file.version";
public static final int PCR_NUMBER = 0;
public static final int PCR_VALUE = 1;
}

View File

@ -7,7 +7,6 @@ import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.UnmarshalException;
import javax.xml.crypto.dsig.keyinfo.*;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Source;
import javax.xml.transform.TransformerFactory;
@ -51,7 +50,6 @@ import org.xml.sax.SAXException;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.ByteArrayInputStream;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
@ -66,14 +64,11 @@ import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.math.BigInteger;
import hirs.swid.utils.CsvParser;
import hirs.swid.xjc.Directory;
import hirs.swid.xjc.Entity;
import hirs.swid.xjc.Link;
@ -95,21 +90,9 @@ import com.eclipsesource.json.ParseException;
*/
public class SwidTagGateway {
private static final QName _DEFAULT_QNAME = new QName(
"http://www.w3.org/2000/09/xmldsig#", "SHA256", "ds");
private static final QName _SHA1Value_QNAME = new QName(
"http://www.w3.org/2000/09/xmldsig#", "SHA1", "ds");
private static final QName _SHA384Value_QNAME = new QName(
"http://www.w3.org/2000/09/xmldsig#", "SHA384", "ds");
private static final QName _SHA512Value_QNAME = new QName(
"http://www.w3.org/2000/09/xmldsig#", "SHA512", "ds");
private static final QName _SHA256_HASH = new QName(
"http://www.w3.org/2001/04/xmlenc#sha256", "hash", "SHA256");
private final ObjectFactory objectFactory = new ObjectFactory();
private final File generatedFile = new File("generated_swidTag.swidtag");
private QName hashValue = null;
private JAXBContext jaxbContext;
private Marshaller marshaller;
private Unmarshaller unmarshaller;
@ -304,7 +287,7 @@ public class SwidTagGateway {
* This method creates an Entity object based on the parameters read in from
* a properties file.
*
* @param properties the Properties object containing parameters from file
* @param jsonObject the Properties object containing parameters from file
* @return Entity object created from the properties
*/
private Entity createEntity(JsonObject jsonObject) {
@ -341,7 +324,7 @@ public class SwidTagGateway {
/**
* Thsi method creates a Link element based on the parameters read in from a properties
* file.
* @param properties the Properties object containing parameters from file
* @param jsonObject the Properties object containing parameters from file
* @return Link element created from the properties
*/
private Link createLink(JsonObject jsonObject) {
@ -361,7 +344,7 @@ public class SwidTagGateway {
/**
* This method creates a Meta element based on the parameters read in from a properties
* file.
* @param properties the Properties object containing parameters from file
* @param jsonObject the Properties object containing parameters from file
* @return the Meta element created from the properties
*/
private SoftwareMeta createSoftwareMeta(JsonObject jsonObject) {
@ -392,15 +375,15 @@ public class SwidTagGateway {
/**
* This method creates a Payload from the parameters read in from a properties file.
*
* @param properties the Properties object containing parameters from file
* @param jsonObject the Properties object containing parameters from file
* @return the Payload object created
*/
private ResourceCollection createPayload(JsonObject jsonObject) {
ResourceCollection payload = objectFactory.createResourceCollection();
Map<QName, String> attributes = payload.getOtherAttributes();
addNonNullAttribute(attributes, SwidTagConstants._N8060_ENVVARPREFIX, jsonObject.getString(SwidTagConstants.PAYLOAD_ENVVARPREFIX, ""));
addNonNullAttribute(attributes, SwidTagConstants._N8060_ENVVARSUFFIX, jsonObject.getString(SwidTagConstants.PAYLOAD_ENVVARSUFFIX, ""));
addNonNullAttribute(attributes, SwidTagConstants._N8060_PATHSEPARATOR, jsonObject.getString(SwidTagConstants.PAYLOAD_PATHSEPARATOR, ""));
addNonNullAttribute(attributes, SwidTagConstants._N8060_ENVVARPREFIX, jsonObject.getString(SwidTagConstants._N8060_ENVVARPREFIX.getLocalPart(), ""));
addNonNullAttribute(attributes, SwidTagConstants._N8060_ENVVARSUFFIX, jsonObject.getString(SwidTagConstants._N8060_ENVVARSUFFIX.getLocalPart(), ""));
addNonNullAttribute(attributes, SwidTagConstants._N8060_PATHSEPARATOR, jsonObject.getString(SwidTagConstants._N8060_PATHSEPARATOR.getLocalPart(), ""));
return payload;
}
@ -408,7 +391,7 @@ public class SwidTagGateway {
/**
* This method creates a Directory from the parameters read in from a properties file.
*
* @param properties the Properties object containing parameters from file
* @param jsonObject the Properties object containing parameters from file
* @return Directory object created from the properties
*/
private Directory createDirectory(JsonObject jsonObject) {
@ -418,13 +401,7 @@ public class SwidTagGateway {
addNonNullAttribute(attributes, SwidTagConstants._SUPPORT_RIM_TYPE, jsonObject.getString(SwidTagConstants.SUPPORT_RIM_TYPE, ""));
addNonNullAttribute(attributes, SwidTagConstants._SUPPORT_RIM_FORMAT, jsonObject.getString(SwidTagConstants.SUPPORT_RIM_FORMAT, ""));
addNonNullAttribute(attributes, SwidTagConstants._SUPPORT_RIM_URI_GLOBAL, jsonObject.getString(SwidTagConstants.SUPPORT_RIM_URI_GLOBAL, ""));
/*
directory.setLocation(jsonObject.getString(SwidTagConstants.DIRECTORY_LOCATION));
String directoryRoot = jsonObject.getString(SwidTagConstants.DIRECTORY_ROOT);
if (!directoryRoot.isEmpty()) {
directory.setRoot(directoryRoot);
}
*/
return directory;
}
@ -432,8 +409,7 @@ public class SwidTagGateway {
* This method creates a hirs.swid.xjc.File from three arguments, then calculates
* and stores its hash as an attribute in itself.
*
* @param filename
* @param location
* @param jsonObject
* @return hirs.swid.xjc.File object from File object
*/
private hirs.swid.xjc.File createFile(JsonObject jsonObject) {

View File

@ -50,7 +50,7 @@ public class TestSwidTagGateway {
/**
* This test corresponds to the arguments:
* -c base
* -c base -a attributes.json
* -c base -a <path>
*/
@Test
public void testCreateBaseWithoutCert() {
@ -61,7 +61,8 @@ public class TestSwidTagGateway {
}
/**
* Validate a base RIM with default attributes with an X509Certificate element.
* This test corresponds to the arguments:
* -v <path> -p RimSignCert.pem
*/
@Test
public void testValidateSwidTag() {