Compare Revisions

The credentials to download the source code are:
 Username: svnusers
 Password: svnusers

Ignore whitespace Rev 1912 → Rev 1913

/branches/Security/javasrc/certificatesio/org/etsi/certificates/CertificatesIOFactory.java
6,11 → 6,6
public class CertificatesIOFactory {
/**
* The single instance of this class.
*/
private static CertificatesIOFactory _instance = new CertificatesIOFactory();
/**
* The single instance of the class CertificatesIO.
*/
private static ICertificatesIO _certIO = new CertificatesIO();
20,7 → 15,7
* @return The single instance of this class.
*/
public static ICertificatesIO getInstance() {
return _instance._certIO;
return _certIO;
}
/**
/branches/Security/javasrc/certificatesio/org/etsi/certificates/Helpers.java
7,6 → 7,7
 
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FilenameFilter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
68,32 → 69,46
 
/**
* Recursively walk a directory tree and return a List of all Files found; the List is sorted using File.compareTo().
* @param startingDir is a valid directory, which can be read.
* @param p_startingDir The valid directory, which can be read.
* @param p_extension The file extension, in lower case
* @param p_excludedPatterns The pattern which shall be excluded, in lower case
*/
public List<File> getFileListing(File startingDir) throws FileNotFoundException {
validateDirectory(startingDir);
List<File> result = getFileListingNoSort(startingDir);
public List<File> getFileListing(File p_startingDir, final String p_extension, final String[] p_excludedPatterns) throws FileNotFoundException {
validateDirectory(p_startingDir);
List<File> result = getFileListingNoSort(p_startingDir, p_extension, p_excludedPatterns);
Collections.sort(result);
return result;
}
 
private List<File> getFileListingNoSort(File startingDir) throws FileNotFoundException {
private List<File> getFileListingNoSort(final File p_startingDir, final String p_extension, final String[] p_excludedPatterns) throws FileNotFoundException {
List<File> result = new ArrayList<File>();
File[] filesAndDirs = startingDir.listFiles();
FilenameFilter filter = new FilenameFilter() {
@Override
public boolean accept(final File p_dirName, final String p_fileName) {
String name = p_fileName.toLowerCase();
if (!p_extension.isEmpty() && !name.endsWith(p_extension)) {
return false;
}
if (p_excludedPatterns != null) {
for (String excludePattern : p_excludedPatterns) {
if (name.indexOf(excludePattern) != -1) {
return false;
}
}
}
return true;
}
};
File[] filesAndDirs = p_startingDir.listFiles(filter);
List<File> filesDirs = Arrays.asList(filesAndDirs);
for (File file : filesDirs) {
if (file.isDirectory() && ((file.getName().indexOf(".svn") != -1)
|| (file.getName().indexOf("._.DS_Store") != -1)
|| (file.getName().indexOf(".DS_Store") != -1))) { // For debug purpose only
// Skip svn files
continue;
}
result.add(file); // always add, even if directory
if (!file.isFile()) {
//must be a directory
//recursive call!
List<File> deeperList = getFileListingNoSort(file);
List<File> deeperList = getFileListingNoSort(file, p_extension, p_excludedPatterns);
result.addAll(deeperList);
}
}
/branches/Security/javasrc/certificatesio/org/etsi/certificates/io/CertificatesIO.java
13,65 → 13,49
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
 
import org.etsi.certificates.Helpers;
import org.etsi.common.ByteHelper;
 
import de.fraunhofer.sit.c2x.CryptoLib;
 
public class CertificatesIO implements ICertificatesIO {
/**
* Regex pattern to extract signing private key
* Relative path for to extract certificates
*/
private static final String SIGNING_PRIVATE_KEY_PATTERN = "^SigningPrivate key\\s*=\\s*([A-Fa-f0-9]+)$";
private static final String CERTS_PATH = "/certs_store";
/**
* Regex pattern to extract encrypt private key
* Extension file for private keys
*/
private static final String ENCRYPT_PRIVATE_KEY_PATTERN = "^EncryptPrivate key\\s*=\\s*([A-Fa-f0-9]+)$";
private static final String KEYS_EXT = "bin";
/**
* Regex pattern to extract AA certificate
* Relative path for to extract private keys
*/
private static final String CERT_AA_PATTERN = "^AUTHORIZATION_AUTHORITY.dump\\s*=\\s*([A-Fa-f0-9]+)$";
private static final String KEYS_PATH = "/priv_keys";
/**
* Regex pattern to extract AT certificate
* Full path to access certificate files
*/
private static final String CERT_AT_PATTERN = "^AUTHORIZATION_TICKET.dump\\s*=\\s*([A-Fa-f0-9]+)$";
private String _fullPathCerts;
/**
* Regex compiler to extract signing private key
* Full path to access key files
*/
private Pattern signingPrivateKeyPattern = Pattern.compile(SIGNING_PRIVATE_KEY_PATTERN, Pattern.MULTILINE);
private String _fullPathKeys;
/**
* Regex compiler to extract encrypt private key
* Memory cache for the certificates
*/
private Pattern encryptPrivateKeyPattern = Pattern.compile(ENCRYPT_PRIVATE_KEY_PATTERN, Pattern.MULTILINE);
private Map<String, byte[]> _cachedCertificates;
/**
* Regex compiler to extract AA certificate
*/
private Pattern certAaPattern = Pattern.compile(CERT_AA_PATTERN, Pattern.MULTILINE);
private Map<String, byte[]> _cachedCertificatesDigest;
/**
* Regex compiler to extract AT certificate
*/
private Pattern certAtPattern = Pattern.compile(CERT_AT_PATTERN, Pattern.MULTILINE);
private Map<String, String> _cachedReverseCertificatesDigest;
/**
* Full path to access certificate files
*/
private String _fullPath;
/**
* Memory cache for the certificates
*/
private Map<String, byte[]> _cachedCertificates;
/**
* Memory cache for the signing private keys
*/
private Map<String, byte[]> _cachedSigningPrivateKey;
86,8 → 70,10
*/
public CertificatesIO() {
_cachedCertificates = new ConcurrentHashMap<String, byte[]>();
_cachedCertificatesDigest = new ConcurrentHashMap<String, byte[]>();
_cachedSigningPrivateKey = new ConcurrentHashMap<String, byte[]>();
_cachedEncryptPrivateKey = new ConcurrentHashMap<String, byte[]>();
_cachedReverseCertificatesDigest = new ConcurrentHashMap<String, String>();
} // End of Constructor
/**
99,31 → 85,36
@Override
public boolean loadCertificates(final String rootDirectory, final String configId) { // E.g. <rootDirectory path>, cfg01
// Initialise the memory caches
_cachedCertificates.clear();
_cachedSigningPrivateKey.clear();
_cachedEncryptPrivateKey.clear();
unloadCertificates();
// Build full path
if ((rootDirectory == null) || (rootDirectory.length() == 0)) {
_fullPath = System.getProperty("user.dir").replace("\\", "/");
_fullPathCerts = System.getProperty("user.dir").replace("\\", "/");
} else {
_fullPath = rootDirectory.replace("\\", "/");
_fullPathCerts = rootDirectory.replace("\\", "/");
}
if (!_fullPath.endsWith("/")) {
_fullPath += "/";
if (!_fullPathCerts.endsWith("/")) {
_fullPathCerts += "/";
}
if ((configId != null) && (configId.length() != 0)) {
_fullPath += configId.replace('.', '/');
_fullPathCerts += configId.replace('.', '/');
}
_fullPath = _fullPath.toLowerCase();
// Check the path
File path = new File(_fullPath);
if (!path.exists()) {
System.err.println("CertificatesIO.readCertificate: path '" + _fullPath + "' does not found");
_fullPathCerts = _fullPathCerts.toLowerCase();
_fullPathKeys = _fullPathCerts + KEYS_PATH;
_fullPathCerts += CERTS_PATH;
// Check the paths
File keysPath = new File(_fullPathKeys);
if (!keysPath.exists()) {
System.err.println("CertificatesIO.readCertificate: path '" + _fullPathKeys + "' does not found");
return false;
}
File certsPath = new File(_fullPathCerts);
if (!certsPath.exists()) {
System.err.println("CertificatesIO.readCertificate: path '" + _fullPathCerts + "' does not found");
return false;
}
return loadMemoryCache(path); // Load certificates and keys and return
return loadMemoryCache(keysPath); // Load certificates and keys and return
}
/**
132,9 → 123,13
*/
@Override
public boolean unloadCertificates() {
_fullPath = null;
_fullPathKeys = null;
_fullPathCerts = null;
_cachedCertificates.clear();
_cachedCertificatesDigest.clear();
_cachedSigningPrivateKey.clear();
_cachedEncryptPrivateKey.clear();
_cachedReverseCertificatesDigest.clear();
return true;
}
163,6 → 158,26
return false;
}
@Override
public boolean readCertificateDigest(final String certificateId, final ByteArrayOutputStream digest) {
// Sanity check
String key = certificateId + ".DIGEST";
if (!_cachedCertificatesDigest.containsKey(key)) {
System.err.println("CertificatesIO.readCertificate: key '" + key + "' not found");
return false;
}
try {
digest.write(_cachedCertificatesDigest.get(key));
return true;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return false;
}
/**
* @desc Read the private keys for the specified certificate
* @param keysId the keys identifier
189,10 → 204,16
return false;
}
private boolean loadMemoryCache(final File path) { // E.g. <path>/ta_config_a.txt
// Retrieve the list of the files in the _fullpath
/**
* @desc Load certificates based on existing keys file, excluding xxx_at.bin files
* @param p_keysPath path for private key files
* @param p_certsPath Path for certificate files
* @return true on success, false otherwise
*/
private boolean loadMemoryCache(final File p_keysPath) { // E.g. <path>/keys, <path>/certs
// Retrieve the list of the files in the p_keysPath
try {
List<File> files = Helpers.getInstance().getFileListing(path);
List<File> files = Helpers.getInstance().getFileListing(p_keysPath, KEYS_EXT, new String[] { "_at", "_aa", /*for debug: */".svn", "._.DS_Store", ".DS_Store"});
// Create the memory cache
for (File file : files) {
addItem(file);
205,47 → 226,87
return false;
}
 
private void addItem(final File file) throws FileNotFoundException, IOException {
String key = file.getName().substring(0, file.getName().indexOf('.')).toUpperCase();
private void addItem(final File p_keysFile) throws FileNotFoundException, IOException {
// Sanity checks
if (p_keysFile.length() != 32) { // FIXME Should have both encrypt and singing keys
return;
}
// Load the keys file name
String filename = p_keysFile.getName().toLowerCase();
String keysFileName = filename.substring(0, filename.indexOf("_ca"));
File caFile = new File(_fullPathCerts + "/" + keysFileName + "_ca.crt");
File aaFile = new File(_fullPathCerts + "/" + keysFileName + "_aa.crt");
File atFile = new File(_fullPathCerts + "/" + keysFileName + "_at.crt");
String key = keysFileName.toUpperCase();
if (!_cachedCertificates.containsKey(key)) {
FileInputStream fs = new FileInputStream(file.getCanonicalPath());
byte bytes[] = new byte[(int) file.length()];
fs.read(bytes);
String content = new String(bytes);
// Open CA keys file
FileInputStream fsKeys = new FileInputStream(p_keysFile.getCanonicalPath());
// Load keys
byte bytes[] = new byte[(int) p_keysFile.length()];
fsKeys.read(bytes);
_cachedSigningPrivateKey.put(key + ".CA_PRIVATE_KEYS", ByteHelper.extract(bytes, 0, 32));
// FIXME Should have both encrypt and singing keys _cachedEncryptPrivateKey.put(key + ".PRIVATE_KEYS", ByteHelper.extract(bytes, 32, 32));
_cachedEncryptPrivateKey.put(key + ".CA_PRIVATE_KEYS", ByteHelper.extract(bytes, 0, 32));
// Close file stream
fsKeys.close();
// Open CA keys file
fsKeys = new FileInputStream(p_keysFile.getCanonicalPath().toLowerCase().replaceAll("_ca", "_at"));
// Load keys
bytes = new byte[(int) p_keysFile.length()];
fsKeys.read(bytes);
_cachedSigningPrivateKey.put(key + ".AT_PRIVATE_KEYS", ByteHelper.extract(bytes, 0, 32));
// FIXME Should have both encrypt and singing keys _cachedEncryptPrivateKey.put(key + ".PRIVATE_KEYS", ByteHelper.extract(bytes, 32, 32));
_cachedEncryptPrivateKey.put(key + ".AT_PRIVATE_KEYS", ByteHelper.extract(bytes, 0, 32));
// Close file stream
fsKeys.close();
// Extract SigningPrivateKey. Key identifier is key.PRIVATE_KEYS
// E.g. SigningPrivate key=68E45C8BBE0ABFA80188E62D082D7A1E5FD4D637D99A5826781280F3865B5819
Matcher matcher = signingPrivateKeyPattern.matcher(content);
if (matcher.find()) {
// System.out.println("CertificatesIO.addItem: Add key '" + key + ".PRIVATE_KEYS" + "'");
_cachedSigningPrivateKey.put(key + ".PRIVATE_KEYS", ByteHelper.hexStringToByteArray(matcher.group(1)));
}
// Extract EncryptPrivate. Key identifier is key.PRIVATE_KEYS
// E.g. EncryptPrivate key=00B65233550BE5A9866CF871D7712691CC47532A08C620D20579FB02BEFA3D1C5F
matcher = encryptPrivateKeyPattern.matcher(content);
if (matcher.find()) {
// System.out.println("CertificatesIO.addItem: Add key '" + key + ".PRIVATE_KEYS" + "'");
_cachedEncryptPrivateKey.put(key + ".PRIVATE_KEYS", ByteHelper.hexStringToByteArray(matcher.group(1)));
}
// Open CA certificate
FileInputStream fsCaFile = new FileInputStream(caFile.getCanonicalPath());
bytes = new byte[(int) caFile.length()];
fsCaFile.read(bytes);
_cachedCertificates.put(key + ".CA_CERT", bytes);
// Close file streams
fsCaFile.close();
// Extract AUTHORIZATION_AUTHORITY.dump. Key identifier is key.AA_CERT
// E.g. AUTHORIZATION_AUTHORITY.dump=02015791FDC6CE82402F0210455453495F506C7567746573745F414180910000040E5F7F47D7A165E2DC403F1E8BAA14E6FF04ADE282CB22212056444CE0F193B01493338B6A8A5D36B2BE9CD3D1F5C708862BCD4539F9D99A0D9F7347066A92C001010004402A571AF5293651B3E2A931CEB1009805EB92E44288D08510E67BA629F14D61402A571AF5293651B3E2A931CEB1009805EB92E44288D08510E67BA629F14D6102202006C04080C040812401146757031A5617030303181DB9CF7C052616001DB9566E0526872A1D53F0D0052783500000A3EECD601A7D17D4C1EB4B8205EEFAE45E170872D49741941B5C9AEDEAA76E38938A67F98DCD46D390B9CF4C16AD324B9E6520565994790029A841E4C820BE4D
matcher = certAaPattern.matcher(content);
if (matcher.find()) {
// System.out.println("CertificatesIO.addItem: Add key '" + key + ".AA_CERT" + "'");
_cachedCertificates.put(key + ".AA_CERT", ByteHelper.hexStringToByteArray(matcher.group(1)));
}
// Open AA certificate
FileInputStream fsAaFile = new FileInputStream(aaFile.getCanonicalPath());
bytes = new byte[(int) aaFile.length()];
fsAaFile.read(bytes);
_cachedCertificates.put(key + ".AA_CERT", bytes);
// Close file streams
fsAaFile.close();
// Extract AUTHORIZATION_TICKET.dump. Key identifier is key.AT_CERT
// E.g. AUTHORIZATION_TICKET.dump=0201CDF3567352CD8B4401008095000004DCBD7FBD344A653D42420350D3CB84E68C1E618ACC16FF4BA31D9D2913530A1ADED6F691D23476E779CCA54C63327F28E9E943929CF5C459DDA01E459279CAA0010100041D2EE0E362BF2798C5148BB198B2EB3718CB0B8714580A70A7161A5550D71F364FF1D5098A18E2B9CE142A17B5558A9E54438823D146CC24A372E7CE1761AF100220210AC040800100C0408101002401146757031A5617030303181DB9CF7C052616001DB9566E0526872A1D53F0D0052783500000AE35B36EA820B183AD0AD732656E2606A8C373C95DFA580FF4C049C66FEFD76F0B558C16932B4DC2BA0D52966AC3D56AC20E606DEDE63B625B4B80FDE1269335
matcher = certAtPattern.matcher(content);
if (matcher.find()) {
// System.out.println("CertificatesIO.addItem: Add key '" + key + ".AT_CERT" + "'");
_cachedCertificates.put(key + ".AT_CERT", ByteHelper.hexStringToByteArray(matcher.group(1)));
}
// Open AT certificate
FileInputStream fsAtFile = new FileInputStream(atFile.getCanonicalPath());
bytes = new byte[(int) atFile.length()];
fsAtFile.read(bytes);
_cachedCertificates.put(key + ".AT_CERT", bytes);
byte[] digest = calculateDigestFromCertificate(bytes);
_cachedCertificatesDigest.put(key + ".AT_CERT.DIGEST", digest);
_cachedReverseCertificatesDigest.put(ByteHelper.byteArrayToString(digest), key + ".AT_CERT.DIGEST");
// Close file streams
fsAtFile.close();
} // else, ignore it
}
@Override
public String getKeyIdFromHashedId8(byte[] p_hashedId8ToBeUsed) {
String key = ByteHelper.byteArrayToString(p_hashedId8ToBeUsed);
if (!_cachedReverseCertificatesDigest.containsKey(key)) {
return null;
}
return _cachedReverseCertificatesDigest.get(key).substring(0, key.length() - 7/*.DIGEST*/);
}
private byte[] calculateDigestFromCertificate(final byte[] p_toBeHashedData) {
byte[] hash = CryptoLib.hashWithSha256(p_toBeHashedData);
return ByteHelper.extract(hash, hash.length - 8, 8);
}
} // End of class CertificatesIO
/branches/Security/javasrc/certificatesio/org/etsi/certificates/io/ICertificatesIO.java
37,6 → 37,14
boolean readCertificate(final String certificateId, final ByteArrayOutputStream certificate);
/**
* @desc Read the specified certificate digest
* @param certificateId the certificate identifier
* @param digest the expected digest
* @return true on success, false otherwise
*/
boolean readCertificateDigest(final String certificateId, final ByteArrayOutputStream digest);
/**
* @desc Read the private keys for the specified certificate
* @param keysId the keys identifier
* @param signingPrivateKey the signing private key
45,4 → 53,11
*/
boolean readPrivateKeys(final String keysName, final ByteArrayOutputStream signingPrivateKey, final ByteArrayOutputStream encryptPrivateKey);
/**
* @desc Retrieve the key identifier associated to the Digest value
* @param p_hashedId8ToBeUsed the Digest value
* @return The key identifier
*/
String getKeyIdFromHashedId8(final byte[] p_hashedId8ToBeUsed);
} // End of interface ICertificatesIO