From 01970c0672f9b8f4dbf9a35f40e8b0d3d67c0554 Mon Sep 17 00:00:00 2001 From: Nils Schwabe Date: Mon, 5 May 2014 18:23:02 +0200 Subject: Fix message signing --- src/main/java/org/openslx/imagemaster/Globals.java | 28 +-- .../java/org/openslx/imagemaster/db/LdapUser.java | 2 +- .../openslx/imagemaster/ftp/ImageProcessor.java | 5 +- .../openslx/imagemaster/ftp/MasterFtpServer.java | 6 +- .../serversession/ServerAuthenticator.java | 13 +- .../openslx/imagemaster/session/Authenticator.java | 2 +- .../openslx/imagemaster/util/AsymMessageSign.java | 66 +++---- src/test/java/org/openslx/imagemaster/AppTest.java | 8 - .../java/org/openslx/imagemaster/ServerTest.java | 200 ++++++++++----------- 9 files changed, 158 insertions(+), 172 deletions(-) (limited to 'src') diff --git a/src/main/java/org/openslx/imagemaster/Globals.java b/src/main/java/org/openslx/imagemaster/Globals.java index 3dedc82..a03d401 100644 --- a/src/main/java/org/openslx/imagemaster/Globals.java +++ b/src/main/java/org/openslx/imagemaster/Globals.java @@ -22,7 +22,7 @@ public class Globals public static enum PropString { - IMAGEDIR, KEYSTOREFILE, KEYSTOREALIAS, KEYSTOREPASSWORD, LDAPHOST, LDAPBINDQUERY, LDAPSEARCHBASEDN, LDAPSEARCHFILTER, LDAPKEYSTOREPASSWORD, LDAPKEYSTOREPATH, FTPBASEDIR + IMAGEDIR, FTPKEYSTOREFILE, FTPKEYSTOREALIAS, FTPKEYSTOREPASSWORD, LDAPHOST, LDAPBINDQUERY, LDAPSEARCHBASEDN, LDAPSEARCHFILTER, LDAPKEYSTOREPASSWORD, LDAPKEYSTOREPATH, FTPBASEDIR } public static enum PropBool @@ -67,12 +67,12 @@ public class Globals || Globals.getPropertyString( PropString.LDAPKEYSTOREPATH ).isEmpty() || Globals.getPropertyString( PropString.FTPBASEDIR ) == null || Globals.getPropertyString( PropString.FTPBASEDIR ).isEmpty() - || Globals.getPropertyString( PropString.KEYSTOREFILE ) == null - || Globals.getPropertyString( PropString.KEYSTOREFILE ).isEmpty() - || Globals.getPropertyString( PropString.KEYSTOREALIAS ) == null - || Globals.getPropertyString( PropString.KEYSTOREALIAS ).isEmpty() - || Globals.getPropertyString( PropString.KEYSTOREPASSWORD ) == null - || Globals.getPropertyString( PropString.KEYSTOREPASSWORD ).isEmpty() + || Globals.getPropertyString( PropString.FTPKEYSTOREFILE ) == null + || Globals.getPropertyString( PropString.FTPKEYSTOREFILE ).isEmpty() + || Globals.getPropertyString( PropString.FTPKEYSTOREALIAS ) == null + || Globals.getPropertyString( PropString.FTPKEYSTOREALIAS ).isEmpty() + || Globals.getPropertyString( PropString.FTPKEYSTOREPASSWORD ) == null + || Globals.getPropertyString( PropString.FTPKEYSTOREPASSWORD ).isEmpty() || Globals.getPropertyInt( PropInt.LDAPPORT ) == 0 || Globals.getPropertyInt( PropInt.SESSIONTIMEOUTUSER ) == 0 @@ -95,7 +95,7 @@ public class Globals } // check keystore - if ( !Globals.getPropertyString( PropString.KEYSTOREFILE ).endsWith( ".jks" )) { + if ( !Globals.getPropertyString( PropString.FTPKEYSTOREFILE ).endsWith( ".jks" )) { log.error( "Keystore is not in jks format." ); return false; } @@ -153,14 +153,14 @@ public class Globals case IMAGEDIR: result = properties.getProperty( "image_dir" ); break; - case KEYSTOREFILE: - result = properties.getProperty( "keystore_file" ); + case FTPKEYSTOREFILE: + result = properties.getProperty( "ftp_keystore_file" ); break; - case KEYSTOREALIAS: - result = properties.getProperty( "keystore_alias" ); + case FTPKEYSTOREALIAS: + result = properties.getProperty( "ftp_keystore_alias" ); break; - case KEYSTOREPASSWORD: - result = properties.getProperty( "keystore_password" ); + case FTPKEYSTOREPASSWORD: + result = properties.getProperty( "ftp_keystore_password" ); break; case LDAPHOST: result = properties.getProperty( "ldap_host" ); diff --git a/src/main/java/org/openslx/imagemaster/db/LdapUser.java b/src/main/java/org/openslx/imagemaster/db/LdapUser.java index ae6aae2..0299829 100644 --- a/src/main/java/org/openslx/imagemaster/db/LdapUser.java +++ b/src/main/java/org/openslx/imagemaster/db/LdapUser.java @@ -153,7 +153,7 @@ public class LdapUser extends User /** * Login user locally if external Ldap server is not available - * @param username Must be in form "userid@organization" + * @param username Must be in form "username@organization" * @param password The user's password */ private static LdapUser localLogin( String login, String password ) diff --git a/src/main/java/org/openslx/imagemaster/ftp/ImageProcessor.java b/src/main/java/org/openslx/imagemaster/ftp/ImageProcessor.java index 62475e9..05b8101 100644 --- a/src/main/java/org/openslx/imagemaster/ftp/ImageProcessor.java +++ b/src/main/java/org/openslx/imagemaster/ftp/ImageProcessor.java @@ -115,12 +115,9 @@ public class ImageProcessor if (!imageData.uuid.matches( "^[0-9a-f]{8}\\-[0-9a-f]{4}\\-[0-9a-f]{4}\\-[0-9a-f]{4}\\-[0-9a-f]{12}$" )) { log.debug("UUID not valid"); return false; - } else if (!imageData.imageName.matches( "^[a-zA-Z0-9_\\-]{50}$" )) { + } else if (!imageData.imageName.matches( "^[a-zA-Z0-9_\\-]{5,50}$" )) { log.debug("ImageName not valid"); return false; - } else if (!imageData.imageOwner.matches( "^[0-9]*$" )) { - log.debug("ImageOwner not valid"); - return false; } // TODO: check some more regex diff --git a/src/main/java/org/openslx/imagemaster/ftp/MasterFtpServer.java b/src/main/java/org/openslx/imagemaster/ftp/MasterFtpServer.java index e3514f6..0f5267f 100644 --- a/src/main/java/org/openslx/imagemaster/ftp/MasterFtpServer.java +++ b/src/main/java/org/openslx/imagemaster/ftp/MasterFtpServer.java @@ -46,9 +46,9 @@ public class MasterFtpServer implements Runnable // config ssl SslConfigurationFactory sslConfigFactory = new SslConfigurationFactory(); - sslConfigFactory.setKeystoreFile( new File( Globals.getPropertyString( PropString.KEYSTOREFILE ) ) ); - sslConfigFactory.setKeyAlias( Globals.getPropertyString( PropString.KEYSTOREALIAS ) ); - sslConfigFactory.setKeystorePassword( Globals.getPropertyString( PropString.KEYSTOREPASSWORD ) ); + sslConfigFactory.setKeystoreFile( new File( Globals.getPropertyString( PropString.FTPKEYSTOREFILE ) ) ); + sslConfigFactory.setKeyAlias( Globals.getPropertyString( PropString.FTPKEYSTOREALIAS ) ); + sslConfigFactory.setKeystorePassword( Globals.getPropertyString( PropString.FTPKEYSTOREPASSWORD ) ); // set the port of the listener factory.setPort( port ); diff --git a/src/main/java/org/openslx/imagemaster/serversession/ServerAuthenticator.java b/src/main/java/org/openslx/imagemaster/serversession/ServerAuthenticator.java index 8a8e426..5660f2f 100644 --- a/src/main/java/org/openslx/imagemaster/serversession/ServerAuthenticator.java +++ b/src/main/java/org/openslx/imagemaster/serversession/ServerAuthenticator.java @@ -5,8 +5,6 @@ import java.util.HashMap; import org.apache.log4j.Logger; import org.apache.thrift.TException; -import org.openslx.imagemaster.Globals; -import org.openslx.imagemaster.Globals.PropString; import org.openslx.imagemaster.thrift.iface.AuthenticationException; import org.openslx.imagemaster.util.AsymMessageSign; import org.openslx.imagemaster.util.RandomString; @@ -24,9 +22,7 @@ public class ServerAuthenticator */ static { try { - messageSign = new AsymMessageSign( Globals.getPropertyString( PropString.KEYSTOREALIAS ), - Globals.getPropertyString( PropString.KEYSTOREPASSWORD ), - Globals.getPropertyString( PropString.KEYSTOREFILE ) ); + messageSign = new AsymMessageSign( "./config/servers.jks", "password" ); log.info( "Loaded keystore" ); } catch ( Exception e ) { log.error( "Error loading the keystore", e ); @@ -54,7 +50,7 @@ public class ServerAuthenticator } /** - * Authenticate with the challengeResponse + * Authenticate with the challengeResponse. * * @param organization * @param address @@ -72,7 +68,7 @@ public class ServerAuthenticator boolean result = false; try { - result = messageSign.verifyMessage( bytes, authenticatingServers.get( organization ).getBytes() ); + result = messageSign.verifyMessage( bytes, authenticatingServers.get( organization ).getBytes() , "uni-freiburg.de" ); } catch ( Exception e ) { log.error( "Error while verifying message", e ); } @@ -81,8 +77,7 @@ public class ServerAuthenticator throw new AuthenticationException(); } - log.info( "Server of organinzation '" + organization - + " authenticated." ); + log.info( "Server of organinzation '" + organization + " authenticated." ); authenticatingServers.remove( organization ); diff --git a/src/main/java/org/openslx/imagemaster/session/Authenticator.java b/src/main/java/org/openslx/imagemaster/session/Authenticator.java index 0796188..5f59a85 100644 --- a/src/main/java/org/openslx/imagemaster/session/Authenticator.java +++ b/src/main/java/org/openslx/imagemaster/session/Authenticator.java @@ -31,7 +31,7 @@ public class Authenticator String login = username; if (username.split( "@" ).length == 2) { log.info( "username is in username@organization format" ); - // we are in userid@organization format + // we are in username@organization format // --> get prefix DbSatellite satellite = DbSatellite.fromOrganization( username.split( "@" )[1] ); if (satellite == null) diff --git a/src/main/java/org/openslx/imagemaster/util/AsymMessageSign.java b/src/main/java/org/openslx/imagemaster/util/AsymMessageSign.java index 134b399..c49f9db 100644 --- a/src/main/java/org/openslx/imagemaster/util/AsymMessageSign.java +++ b/src/main/java/org/openslx/imagemaster/util/AsymMessageSign.java @@ -5,57 +5,59 @@ import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.security.InvalidKeyException; -import java.security.Key; -import java.security.KeyPair; import java.security.KeyStore; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; -import java.security.PrivateKey; import java.security.PublicKey; import java.security.Signature; import java.security.SignatureException; import java.security.UnrecoverableKeyException; -import java.security.cert.Certificate; import java.security.cert.CertificateException; public class AsymMessageSign { - KeyPair pair; + private KeyStore keystore; -// String alias = "ftp"; -// String password = "password"; -// String file = "./config/keystore.jks"; - - - public AsymMessageSign(String alias, String password, String file) throws NoSuchAlgorithmException, CertificateException, FileNotFoundException, IOException, KeyStoreException, UnrecoverableKeyException + /** + * Load the keystore + * @param file Path to keystore + * @param password The keystore's password + * @throws NoSuchAlgorithmException + * @throws CertificateException + * @throws FileNotFoundException + * @throws IOException + * @throws KeyStoreException + * @throws UnrecoverableKeyException + */ + public AsymMessageSign(String file, String password) throws NoSuchAlgorithmException, CertificateException, FileNotFoundException, IOException, KeyStoreException, UnrecoverableKeyException { - KeyStore keystore = KeyStore.getInstance( "JKS" ); + keystore = KeyStore.getInstance( "JKS" ); keystore.load( new FileInputStream( new File( file ) ), password.toCharArray() ); - Certificate cert = null; - - Key key = keystore.getKey( alias, - password.toCharArray() ); - - if ( key instanceof PrivateKey ) { - cert = keystore.getCertificate( alias ); - PublicKey publicKey = cert.getPublicKey(); - pair = new KeyPair( publicKey, (PrivateKey)key ); - } - } - - public byte[] signMessage( String message ) throws NoSuchAlgorithmException, InvalidKeyException, SignatureException - { - Signature signature = Signature.getInstance( "SHA256WITHRSA" ); - signature.initSign( pair.getPrivate() ); - signature.update( message.getBytes() ); - return signature.sign(); } - public boolean verifyMessage( byte[] signedMessage, byte[] realMessage ) throws NoSuchAlgorithmException, InvalidKeyException, SignatureException + /** + * Verify an encrypted message + * @param signedMessage The signed message from hs/uni server + * @param realMessage The message that was sent before + * @param alias the alias of the certificate + * @param password the password of the certificate + * @return Whether the message could be verfied or not + * @throws NoSuchAlgorithmException + * @throws InvalidKeyException + * @throws SignatureException + * @throws UnrecoverableKeyException + * @throws KeyStoreException + */ + public boolean verifyMessage( byte[] signedMessage, byte[] realMessage, String alias ) throws NoSuchAlgorithmException, InvalidKeyException, SignatureException, UnrecoverableKeyException, KeyStoreException { + // first load key + //Key key = keystore.getKey( alias, password.toCharArray() ); + PublicKey key = keystore.getCertificate( alias ).getPublicKey(); + + // verify message Signature signature = Signature.getInstance( "SHA256WITHRSA" ); - signature.initVerify( pair.getPublic() ); + signature.initVerify( key ); signature.update( realMessage ); return signature.verify( signedMessage ); } diff --git a/src/test/java/org/openslx/imagemaster/AppTest.java b/src/test/java/org/openslx/imagemaster/AppTest.java index 2b20b77..cbb6ad2 100644 --- a/src/test/java/org/openslx/imagemaster/AppTest.java +++ b/src/test/java/org/openslx/imagemaster/AppTest.java @@ -52,12 +52,4 @@ public class AppTest extends TestCase { Sha512Crypt.selfTest(); } - - public void testMessageSigning() throws UnrecoverableKeyException, InvalidKeyException, NoSuchAlgorithmException, CertificateException, FileNotFoundException, KeyStoreException, SignatureException, IOException { - String asdf = "Hallo"; - AsymMessageSign mySigner = new AsymMessageSign( "ftp", "password", "./config/keystore.jks" ); - byte[] signedMessage = mySigner.signMessage( asdf ); - System.out.println("The signed message: " + signedMessage + " with length: " + signedMessage.length); - assertTrue("Message could not be verified.", mySigner.verifyMessage( signedMessage, asdf.getBytes() )); - } } diff --git a/src/test/java/org/openslx/imagemaster/ServerTest.java b/src/test/java/org/openslx/imagemaster/ServerTest.java index 5f71fd5..d2a7d14 100644 --- a/src/test/java/org/openslx/imagemaster/ServerTest.java +++ b/src/test/java/org/openslx/imagemaster/ServerTest.java @@ -104,104 +104,104 @@ public class ServerTest extends TestCase * @throws InvalidKeyException * @throws InvalidAlgorithmParameterException */ - public void testServerAuthAndFtpUpload() throws TException, SocketException, IOException, UnrecoverableKeyException, NoSuchAlgorithmException, CertificateException, KeyStoreException, InvalidKeyException, SignatureException, InvalidAlgorithmParameterException - { - if (true) return; - - @SuppressWarnings( "unused" ) - TTransport transport = new TSocket( "localhost", 9090 ); - transport.open(); - - TProtocol protocol = new TBinaryProtocol( transport ); - Client client = new Client( protocol ); - - assertTrue( "Could not ping server", client.ping() ); - - String stringToEncrypt = client.startServerAuthentication( "Test Organization" ); - System.out.println( "Authentication started. Got string: " + stringToEncrypt ); - - AsymMessageSign messageSigner = new AsymMessageSign( "ftp", "password", "./config/keystore.jks" ); - byte[] response = messageSigner.signMessage( stringToEncrypt ); - - System.out.println( "Signed string: " + response ); - ByteBuffer bBuffer = ByteBuffer.wrap( response ); - - ServerSessionData data = client.serverAuthenticate( "Test Organization", bBuffer ); - System.out.println( "Authenticated and got sid: '" + data.getSessionId() + "'" ); - - // Create ImageData - int version = 1; - String imageName = "maschine.vmkd"; - UUID uuid = UUID.randomUUID(); - long imageCreateTime = System.currentTimeMillis(); - long imageUpdateTime = imageCreateTime; - String imageOwner = "ns202"; - String contentOperatingSystem = "win7"; - boolean statusIsValid = true; - boolean statusIsDeleted = false; - String imageShortDescrption = "EIN SUPER TOLLES IMAGE!"; - String imageLongDescription = "Lorem ipsum dolor sit amet."; - - String fileName = "/home/nils/file_to_upload.bin"; - - ImageData imageData = new ImageData( uuid.toString(), version, imageName, - imageCreateTime, imageUpdateTime, imageOwner, contentOperatingSystem, - statusIsValid, statusIsDeleted, imageShortDescrption, imageLongDescription, new File(fileName).getTotalSpace() ); - - System.out.println( "Created imageData..." ); - - FtpCredentials ftpCredentials = client.submitImage( data.sessionId, imageData ); - System.out.println( "Got FTP credentials. User: " + ftpCredentials.username + ", password: " + ftpCredentials.password ); - - FTPSClient FtpClient = new FTPSClient( "SSL", true ); - System.out.println("Created new ftpsclient..."); - TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance( KeyManagerFactory.getDefaultAlgorithm() ); - KeyStore keystore = KeyStore.getInstance( "JKS" ); - keystore.load( new FileInputStream( new File( "./config/keystore.jks" ) ), "password".toCharArray() ); - System.out.println("Loaded keystore.."); - trustManagerFactory.init( keystore ); - TrustManager trustManager = trustManagerFactory.getTrustManagers()[0]; - FtpClient.setTrustManager(trustManager); - - System.out.println("Trying to connect..."); - - String host = "localhost"; - int port = 2221; - String user = ftpCredentials.username; - String password = ftpCredentials.password; - - try { - FtpClient.connect( host, port ); - System.out.println( "Connected to " + host + ":" + port + ". Reply code: " + FtpClient.getReplyCode() ); - if ( !FTPReply.isPositiveCompletion( FtpClient.getReplyCode() ) ) { - throw new ConnectException( "No positive reply code." ); - } - if ( !FtpClient.login( user, password ) ) { - throw new ConnectException( "Could not login." ); - } - System.out.println( "Logged in with user: " + user ); - FtpClient.setFileType( FTP.BINARY_FILE_TYPE ); - FtpClient.enterLocalPassiveMode(); - System.out.println( "Entered PASSIVE MODE" ); - InputStream input = new FileInputStream( fileName ); - System.out.print( "Starting file upload ... " ); - FtpClient.storeFile( "xcvb.vmdk", input ); - System.out.println( "done." ); - FtpClient.noop(); - } catch (Exception e) { - e.printStackTrace(); - } finally { - if ( FtpClient.isConnected() ) { - try { - FtpClient.logout(); - FtpClient.disconnect(); - boolean result = client.finshedUpload( ftpCredentials.username, imageData ); - System.out.println("Telling server that upload finished: " + result); - } catch ( IOException e ) { - e.printStackTrace(); - } - } - } - - } +// public void testServerAuthAndFtpUpload() throws TException, SocketException, IOException, UnrecoverableKeyException, NoSuchAlgorithmException, CertificateException, KeyStoreException, InvalidKeyException, SignatureException, InvalidAlgorithmParameterException +// { +// if (true) return; +// +// @SuppressWarnings( "unused" ) +// TTransport transport = new TSocket( "localhost", 9090 ); +// transport.open(); +// +// TProtocol protocol = new TBinaryProtocol( transport ); +// Client client = new Client( protocol ); +// +// assertTrue( "Could not ping server", client.ping() ); +// +// String stringToEncrypt = client.startServerAuthentication( "Test Organization" ); +// System.out.println( "Authentication started. Got string: " + stringToEncrypt ); +// +// AsymMessageSign messageSigner = new AsymMessageSign( "ftp", "password", "./config/keystore.jks" ); +// byte[] response = messageSigner.signMessage( stringToEncrypt ); +// +// System.out.println( "Signed string: " + response ); +// ByteBuffer bBuffer = ByteBuffer.wrap( response ); +// +// ServerSessionData data = client.serverAuthenticate( "Test Organization", bBuffer ); +// System.out.println( "Authenticated and got sid: '" + data.getSessionId() + "'" ); +// +// // Create ImageData +// int version = 1; +// String imageName = "maschine.vmkd"; +// UUID uuid = UUID.randomUUID(); +// long imageCreateTime = System.currentTimeMillis(); +// long imageUpdateTime = imageCreateTime; +// String imageOwner = "ns202"; +// String contentOperatingSystem = "win7"; +// boolean statusIsValid = true; +// boolean statusIsDeleted = false; +// String imageShortDescrption = "EIN SUPER TOLLES IMAGE!"; +// String imageLongDescription = "Lorem ipsum dolor sit amet."; +// +// String fileName = "/home/nils/file_to_upload.bin"; +// +// ImageData imageData = new ImageData( uuid.toString(), version, imageName, +// imageCreateTime, imageUpdateTime, imageOwner, contentOperatingSystem, +// statusIsValid, statusIsDeleted, imageShortDescrption, imageLongDescription, new File(fileName).getTotalSpace() ); +// +// System.out.println( "Created imageData..." ); +// +// FtpCredentials ftpCredentials = client.submitImage( data.sessionId, imageData ); +// System.out.println( "Got FTP credentials. User: " + ftpCredentials.username + ", password: " + ftpCredentials.password ); +// +// FTPSClient FtpClient = new FTPSClient( "SSL", true ); +// System.out.println("Created new ftpsclient..."); +// TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance( KeyManagerFactory.getDefaultAlgorithm() ); +// KeyStore keystore = KeyStore.getInstance( "JKS" ); +// keystore.load( new FileInputStream( new File( "./config/keystore.jks" ) ), "password".toCharArray() ); +// System.out.println("Loaded keystore.."); +// trustManagerFactory.init( keystore ); +// TrustManager trustManager = trustManagerFactory.getTrustManagers()[0]; +// FtpClient.setTrustManager(trustManager); +// +// System.out.println("Trying to connect..."); +// +// String host = "localhost"; +// int port = 2221; +// String user = ftpCredentials.username; +// String password = ftpCredentials.password; +// +// try { +// FtpClient.connect( host, port ); +// System.out.println( "Connected to " + host + ":" + port + ". Reply code: " + FtpClient.getReplyCode() ); +// if ( !FTPReply.isPositiveCompletion( FtpClient.getReplyCode() ) ) { +// throw new ConnectException( "No positive reply code." ); +// } +// if ( !FtpClient.login( user, password ) ) { +// throw new ConnectException( "Could not login." ); +// } +// System.out.println( "Logged in with user: " + user ); +// FtpClient.setFileType( FTP.BINARY_FILE_TYPE ); +// FtpClient.enterLocalPassiveMode(); +// System.out.println( "Entered PASSIVE MODE" ); +// InputStream input = new FileInputStream( fileName ); +// System.out.print( "Starting file upload ... " ); +// FtpClient.storeFile( "xcvb.vmdk", input ); +// System.out.println( "done." ); +// FtpClient.noop(); +// } catch (Exception e) { +// e.printStackTrace(); +// } finally { +// if ( FtpClient.isConnected() ) { +// try { +// FtpClient.logout(); +// FtpClient.disconnect(); +// boolean result = client.finshedUpload( ftpCredentials.username, imageData ); +// System.out.println("Telling server that upload finished: " + result); +// } catch ( IOException e ) { +// e.printStackTrace(); +// } +// } +// } +// +// } } -- cgit v1.2.3-55-g7522