package org.openslx.satellitedaemon; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.math.BigInteger; import java.nio.charset.StandardCharsets; import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; import java.security.PublicKey; import java.security.spec.InvalidKeySpecException; import java.util.Properties; import java.util.Random; import org.apache.log4j.Logger; import org.openslx.encryption.AsymKeyHolder; import org.openslx.satellitedaemon.util.Util; public class Identity { private static Logger log = Logger.getLogger( Identity.class ); private static final Properties properties = new Properties(); private static String organizationName = null; private static BigInteger privExponent = null; private static BigInteger pubExponent = null; private static BigInteger modulus = null; private static AsymKeyHolder akh = null; public static String getOrganizationName() { return organizationName = properties.getProperty( "ORGANIZATION_NAME" ); } private static BigInteger getModulus() { return modulus = toBigInt( properties.getProperty( "MODULUS" ) ); } private static BigInteger getPublicExponent() { return pubExponent = toBigInt( properties.getProperty( "PUBLIC_EXPONENT" ) ); } private static BigInteger getPrivateExponent() { return privExponent = toBigInt( properties.getProperty( "PRIVATE_EXPONENT" ) ); } /** * Load properties */ static { InputStreamReader stream = null; try { // Load all entries of the config file into properties stream = new InputStreamReader( new FileInputStream( "config/identity.properties" ), StandardCharsets.UTF_8 ); properties.load( stream ); stream.close(); } catch ( IOException e ) { log.error( "Could not load identity.properties. Exiting." ); System.exit( 2 ); } finally { Util.streamClose( stream ); } Util.notNullOrEmptyFatal( getOrganizationName(), "Organiziation Name must not be empty!" ); try { akh = new AsymKeyHolder( getPrivateExponent(), getPublicExponent(), getModulus() ); } catch ( InvalidKeySpecException e ) { log.error( "InvalidKeySpecException", e ); } catch ( NoSuchAlgorithmException e ) { log.error( "NoSuchAlgorithmException", e ); } } /** * Get private key for this server. If none exists yet, create a new one. * * @return */ public static PrivateKey getPrivateKey() { if ( akh != null ) { return akh.getPrivateKey(); } akh = new AsymKeyHolder(); return akh.getPrivateKey(); } /** * Get public key for this server. If none exists yet, create a new one. * * @return */ public static PublicKey getPublicKey() { if ( akh != null ) return akh.getPublicKey(); akh = new AsymKeyHolder(); return akh.getPublicKey(); } /** * Get bit - length of key. * * @return */ public static int keySize( BigInteger modulus ) { return modulus.bitLength(); } /** * Checks if given modulus, private exponent and public exponent are valid * values for key pair. Idea is to encrypt and decrypt random text and compare * the result with initial text. * * @param mod * @param privExp * @param pubExp * @return True, if mod, privExp and pubExp are valid values. */ public static boolean isValidKeyPair( BigInteger mod, BigInteger privExp, BigInteger pubExp ) { // First check given values (modulus, privExp, pubExp). if ( ( mod == null ) || ( privExp == null ) || ( pubExp == null ) ) { log.error( "Given arguments not valid: got NULL for modulus, private or public exponent." ); return false; } // Testing encryption and description with given public and private key. // Idea: creating random text for encrypting and decrypting again. Random rnd = new Random(); int size = rnd.nextInt( keySize( mod ) - 1 ); BigInteger text = new BigInteger( size, rnd ); // Encrypt. BigInteger cipher = text.modPow( pubExp, mod ); // Decrypt again. BigInteger decrypted = cipher.modPow( privExp, mod ); boolean isPassed = text.equals( decrypted ); return isPassed; } public static boolean generateIdentity( String organizationName ) { Identity.organizationName = organizationName; // generate new key pair. Identity.akh = new AsymKeyHolder(); Identity.modulus = akh.getModulus(); Identity.privExponent = akh.getPrivateExponent(); Identity.pubExponent = akh.getPublicExponent(); return writeIdToFile( Identity.organizationName, Identity.modulus, Identity.privExponent, Identity.pubExponent ); } private static boolean writeIdToFile( String organizationName, BigInteger modulus, BigInteger privateExp, BigInteger publicExp ) { File configFile = new File( "config/identity.properties" ); FileOutputStream stream = null; try { stream = new FileOutputStream( configFile ); } catch ( FileNotFoundException e ) { log.error( "FileNotFoundException", e ); return false; } // create strings for writing to file. String orgNameString = "ORGANIZATION_NAME=" + organizationName + "\n"; String modString = "MODULUS=" + modulus.toString() + "\n"; String privExpString = "PRIVATE_EXPONENT=" + privateExp.toString() + "\n"; String pubExpString = "PUBLIC_EXPONENT=" + publicExp.toString() + "\n"; try { stream.write( orgNameString.getBytes() ); stream.write( modString.getBytes() ); stream.write( privExpString.getBytes() ); stream.write( pubExpString.getBytes() ); return true; } catch ( IOException e ) { log.error( "IOException", e ); return false; } finally { try { stream.close(); } catch ( IOException e ) { } } } /** * Check modulus, privExp and pubExp for not being null. * * @return */ private static boolean checkMembers() { return ( ( getModulus() != null ) && ( getPrivateExponent() != null ) && ( getPublicExponent() != null ) ); } /** * Get BigInteger of read String number. * * @param str * @return */ private static BigInteger toBigInt( String str ) { try { return new BigInteger( str ); } catch ( Exception e ) { return null; } } }