diff options
Diffstat (limited to 'id/server')
7 files changed, 258 insertions, 103 deletions
| diff --git a/id/server/moa-id-frontend-resources/src/main/resources/templates/sso_transfer_template.html b/id/server/moa-id-frontend-resources/src/main/resources/templates/sso_transfer_template.html index e9c2fae76..c76e75d64 100644 --- a/id/server/moa-id-frontend-resources/src/main/resources/templates/sso_transfer_template.html +++ b/id/server/moa-id-frontend-resources/src/main/resources/templates/sso_transfer_template.html @@ -3,17 +3,33 @@    <meta content="text/html; charset=utf-8" http-equiv="Content-Type">     <!-- MOA-ID 2.x BKUSelection Layout CSS -->                -  <link rel="stylesheet" href="#CONTEXTPATH#/css/buildCSS" /> +  <link rel="stylesheet" href="$contextPath/css/buildCSS" /> + +  	#if($timeoutURL) +		<script type="text/javascript"> +			function sloTimeOut() { +				window.location.href="$timeoutURL"; +			 +			}	 +	 +		</script> +		#end    <title>Single Sign-On Session Transfer</title>  </head> +#if($timeoutURL) +	<body onload='setTimeout(sloTimeOut, $timeout);'> +#else  	<body> +#end    <noscript>  		<p>  			<strong>Note:</strong> Since your browser does not support  			JavaScript, you must press the Continue button once to proceed.  		</p> +		 +		<a href="$timeoutURL">Press this link to resume</a>  	</noscript>    <div id="page"> diff --git a/id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment/moa/id/auth/modules/ssotransfer/SSOTransferConstants.java b/id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment/moa/id/auth/modules/ssotransfer/SSOTransferConstants.java index ce3a7856b..1ee715afa 100644 --- a/id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment/moa/id/auth/modules/ssotransfer/SSOTransferConstants.java +++ b/id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment/moa/id/auth/modules/ssotransfer/SSOTransferConstants.java @@ -58,8 +58,12 @@ public class SSOTransferConstants {  	public static final String SSOCONTAINER_KEY_USERID = "userID";  	public static final String SSOCONTAINER_KEY_SESSION = "session";  	public static final String SSOCONTAINER_KEY_RESULTENDPOINT = "resultEndPoint"; +	public static final String SSOCONTAINER_KEY_NONCE = "nonce";  	public static final String FLAG_SSO_SESSION_RESTORED = "ssoRestoredFlag";  	public static final long CERT_VALIDITY = 700; //2 years + +	public static final String PENDINGREQ_DH = "dhparams"; +	public static final String PENDINGREQ_NONCE = "nonce";  } diff --git a/id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment/moa/id/auth/modules/ssotransfer/servlet/SSOTransferServlet.java b/id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment/moa/id/auth/modules/ssotransfer/servlet/SSOTransferServlet.java index 2bb31f700..7cf7c914a 100644 --- a/id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment/moa/id/auth/modules/ssotransfer/servlet/SSOTransferServlet.java +++ b/id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment/moa/id/auth/modules/ssotransfer/servlet/SSOTransferServlet.java @@ -30,13 +30,9 @@ import java.io.PrintWriter;  import java.math.BigInteger;  import java.net.URL;  import java.security.InvalidKeyException; -import java.security.KeyFactory; -import java.security.KeyPair; -import java.security.KeyPairGenerator;  import java.security.MessageDigest;  import java.security.NoSuchAlgorithmException;  import java.security.PrivateKey; -import java.security.PublicKey;  import java.security.SecureRandom;  import java.security.Security;  import java.security.spec.InvalidKeySpecException; @@ -46,11 +42,9 @@ import java.util.Date;  import javax.crypto.BadPaddingException;  import javax.crypto.Cipher;  import javax.crypto.IllegalBlockSizeException; -import javax.crypto.KeyAgreement;  import javax.crypto.NoSuchPaddingException;  import javax.crypto.spec.DHParameterSpec;  import javax.crypto.spec.DHPublicKeySpec; -import javax.crypto.spec.SecretKeySpec;  import javax.security.cert.CertificateException;  import javax.security.cert.X509Certificate;  import javax.servlet.http.HttpServletRequest; @@ -467,7 +461,7 @@ public class SSOTransferServlet{  		DHPublicKeySpec mobilePubKeySpec = new DHPublicKeySpec(mobilePubKey,   					container.getDhParams().getF().getP(),   					container.getDhParams().getF().getG()); -		byte[] sharedSecret = getSecret(mobilePubKeySpec, container.getDhParams().getS()); +		byte[] sharedSecret = ssoTransferUtils.getSecret(mobilePubKeySpec, container.getDhParams().getS());  		//build ASE256 key  		MessageDigest digest = MessageDigest.getInstance("SHA-256"); @@ -479,7 +473,7 @@ public class SSOTransferServlet{  		byte[] encryptedCSR = Base64Utils.decode(mobileCSRBase64, true);		  		Logger.debug("EncCSR:" + Base64Utils.encode(encryptedCSR) + " | Key:" + Base64Utils.encode(hashedSecret)); -		byte[] decryptedCSR = enOrDeCryptCSR(encryptedCSR, hashedSecret, Cipher.DECRYPT_MODE); +		byte[] decryptedCSR = ssoTransferUtils.enOrDeCryptCSR(encryptedCSR, hashedSecret, Cipher.DECRYPT_MODE);  		Logger.debug("DecCSR:" + Base64Utils.encode(decryptedCSR));		  		Logger.debug("CSR decryption finished. --> Starting CSR validation and signing ..."); @@ -496,18 +490,16 @@ public class SSOTransferServlet{  		Date now = new Date();  		String personInformationToTransfer =   				ssoTransferUtils.generateSignedAndEncryptedSSOContainer( -						container.getAuthURL(), moaSession, now); +						container.getAuthURL(), moaSession, now, hashedSecret);  		Logger.debug("PersonData:" + personInformationToTransfer);  		//encrypt personal information  		Logger.debug("PersonData generation finished. --> Starting personData encryption ... ");				 -		byte[] encPersonData = enOrDeCryptCSR(personInformationToTransfer.getBytes(), hashedSecret, Cipher.ENCRYPT_MODE); -		String encAndEncodedPersonalData = Base64Utils.encode(encPersonData);  		Logger.debug("Encrypt personData finished. --> Send token to device.");  		resp.setContentType("text/html;charset=UTF-8");  		PrintWriter out = new PrintWriter(resp.getOutputStream());  -		out.print(encAndEncodedPersonalData); +		out.print(personInformationToTransfer);  		out.flush();  		return; @@ -539,7 +531,7 @@ public class SSOTransferServlet{  		BigInteger generator = new BigInteger(Base64Utils.decode(SSOTransferConstants.DH_GENERATOR_BASE64, false));  		DHParameterSpec dhSpec = new DHParameterSpec(prime, generator, 1024); -		Pair<DHPublicKeySpec, PrivateKey> dhKeyIDP = createSpecificKey(dhSpec.getP(), dhSpec.getG()); +		Pair<DHPublicKeySpec, PrivateKey> dhKeyIDP = ssoTransferUtils.createSpecificKey(dhSpec.getP(), dhSpec.getG());  		container.setDhParams(dhKeyIDP);  		//store container							 @@ -575,17 +567,7 @@ public class SSOTransferServlet{  		guiBuilder.build(resp, config, "SSO-Session Transfer-Module");  	} -	 -	public byte[] enOrDeCryptCSR(byte[] binBlob, byte[] binSecret, int mode) throws IllegalBlockSizeException, BadPaddingException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException { -        byte[] decrypted = null; -        SecretKeySpec skeySpec = new SecretKeySpec(binSecret, "AES"); -        Cipher cipher = Cipher.getInstance("AES"); -        cipher.init(mode, skeySpec); -        decrypted = cipher.doFinal(binBlob); - -        return decrypted; -    } -	 +		  	private X509Certificate signCSRWithMOAKey(byte[] inputCSR) throws IOException, OperatorCreationException, PKCSException, CredentialsNotAvailableException, CertificateException {		  		PKCS10CertificationRequest csr = new PKCS10CertificationRequest(inputCSR); @@ -613,20 +595,7 @@ public class SSOTransferServlet{  	} -	 -	private static byte[] getSecret(DHPublicKeySpec kspectrans, PrivateKey privateKey) throws NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException { -		KeyAgreement aKeyAgree = KeyAgreement.getInstance("DiffieHellman"); -		aKeyAgree.init(privateKey); -			 -		KeyFactory kfactory = KeyFactory.getInstance("DiffieHellman"); -		PublicKey pub = kfactory.generatePublic(kspectrans); -		aKeyAgree.doPhase(pub, true); -			 -		byte[] secretKey = aKeyAgree.generateSecret(); -		return secretKey; - -	} -	 +		  	private JsonObject getJSONObjectFromPostMessage(HttpServletRequest req, boolean developmentMode) {  		//read POST request  		StringBuffer sb = new StringBuffer(); @@ -662,20 +631,4 @@ public class SSOTransferServlet{  	} -	private Pair<DHPublicKeySpec, PrivateKey> createSpecificKey(BigInteger p, BigInteger g) throws Exception { -		KeyPairGenerator kpg = KeyPairGenerator.getInstance("DiffieHellman"); - -		DHParameterSpec param = new DHParameterSpec(p, g); -		kpg.initialize(param); -		KeyPair kp = kpg.generateKeyPair(); - -		KeyFactory kfactory = KeyFactory.getInstance("DiffieHellman"); - -		Pair<DHPublicKeySpec, PrivateKey> pair = new Pair<DHPublicKeySpec, PrivateKey>( -		        (DHPublicKeySpec) kfactory.getKeySpec(kp.getPublic(), DHPublicKeySpec.class), kp.getPrivate()); -		return pair; - -	} -	 -	  } diff --git a/id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment/moa/id/auth/modules/ssotransfer/task/InitializeRestoreSSOSessionTask.java b/id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment/moa/id/auth/modules/ssotransfer/task/InitializeRestoreSSOSessionTask.java index e3c8efb50..be27de9a1 100644 --- a/id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment/moa/id/auth/modules/ssotransfer/task/InitializeRestoreSSOSessionTask.java +++ b/id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment/moa/id/auth/modules/ssotransfer/task/InitializeRestoreSSOSessionTask.java @@ -22,6 +22,11 @@   */  package at.gv.egovernment.moa.id.auth.modules.ssotransfer.task; +import java.math.BigInteger; +import java.security.PrivateKey; + +import javax.crypto.spec.DHParameterSpec; +import javax.crypto.spec.DHPublicKeySpec;  import javax.servlet.http.HttpServletRequest;  import javax.servlet.http.HttpServletResponse; @@ -31,12 +36,18 @@ import org.springframework.stereotype.Component;  import at.gv.egovernment.moa.id.auth.frontend.builder.IGUIFormBuilder;  import at.gv.egovernment.moa.id.auth.modules.AbstractAuthServletTask;  import at.gv.egovernment.moa.id.auth.modules.TaskExecutionException; +import at.gv.egovernment.moa.id.auth.modules.ssotransfer.SSOTransferConstants; +import at.gv.egovernment.moa.id.auth.modules.ssotransfer.data.Pair; +import at.gv.egovernment.moa.id.auth.modules.ssotransfer.data.SSOTransferContainer;  import at.gv.egovernment.moa.id.auth.modules.ssotransfer.utils.GUIUtils; +import at.gv.egovernment.moa.id.auth.modules.ssotransfer.utils.SSOContainerUtils;  import at.gv.egovernment.moa.id.commons.api.exceptions.MOAIDException;  import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProviderFactory;  import at.gv.egovernment.moa.id.process.api.ExecutionContext;  import at.gv.egovernment.moa.id.util.HTTPUtils; +import at.gv.egovernment.moa.id.util.Random;  import at.gv.egovernment.moa.logging.Logger; +import at.gv.egovernment.moa.util.Base64Utils;  /**   * @author tlenz @@ -46,6 +57,7 @@ import at.gv.egovernment.moa.logging.Logger;  public class InitializeRestoreSSOSessionTask extends AbstractAuthServletTask {  	@Autowired IGUIFormBuilder guiBuilder; +	@Autowired SSOContainerUtils ssoTransferUtils;  	/* (non-Javadoc)  	 * @see at.gv.egovernment.moa.id.process.springweb.MoaIdTask#execute(at.gv.egovernment.moa.id.process.api.ExecutionContext, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) @@ -64,10 +76,30 @@ public class InitializeRestoreSSOSessionTask extends AbstractAuthServletTask {  				response.sendError(500, "Requested URL is not allowed.");  			} -									 -			GUIUtils.buildSSOTransferGUI(guiBuilder, response, authURL, pendingReq.getRequestID()); + +			//use predefined parameters +			BigInteger prime = new BigInteger(Base64Utils.decode(SSOTransferConstants.DH_PRIME_BASE64, false)); +			BigInteger generator = new BigInteger(Base64Utils.decode(SSOTransferConstants.DH_GENERATOR_BASE64, false)); +			DHParameterSpec dhSpec = new DHParameterSpec(prime, generator, 1024); +								 +			Pair<DHPublicKeySpec, PrivateKey> dhKeyIDP = ssoTransferUtils.createSpecificKey(dhSpec.getP(), dhSpec.getG()); +			String nonce = Random.nextLongRandom(); +			GUIUtils.buildSSOTransferGUI(guiBuilder, response, authURL,  +					pendingReq.getRequestID(), nonce, dhKeyIDP.getF()); +			//store DH params and nonce to pending-request +			SSOTransferContainer container = new SSOTransferContainer(); +			container.setDhParams(dhKeyIDP); +			pendingReq.setGenericDataToSession(SSOTransferConstants.PENDINGREQ_DH, container); +			pendingReq.setGenericDataToSession(SSOTransferConstants.PENDINGREQ_NONCE, nonce); +						 +			//store pending-request +			requestStoreage.storePendingRequest(pendingReq); +			 +			//set flag +			executionContext.put("sessionRestoreFinished", false); +									  		} catch (MOAIDException e) {  			throw new TaskExecutionException(pendingReq, e.getMessage(), e); diff --git a/id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment/moa/id/auth/modules/ssotransfer/task/RestoreSSOSessionTask.java b/id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment/moa/id/auth/modules/ssotransfer/task/RestoreSSOSessionTask.java index 526f45be3..6d9b43e5b 100644 --- a/id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment/moa/id/auth/modules/ssotransfer/task/RestoreSSOSessionTask.java +++ b/id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment/moa/id/auth/modules/ssotransfer/task/RestoreSSOSessionTask.java @@ -24,12 +24,15 @@ package at.gv.egovernment.moa.id.auth.modules.ssotransfer.task;  import java.io.BufferedReader;  import java.io.IOException; +import java.math.BigInteger; +import java.security.MessageDigest; +import javax.crypto.Cipher; +import javax.crypto.spec.DHPublicKeySpec;  import javax.servlet.http.HttpServletRequest;  import javax.servlet.http.HttpServletResponse;  import org.apache.commons.lang3.BooleanUtils; -import org.apache.velocity.VelocityContext;  import org.joda.time.DateTime;  import org.opensaml.saml2.core.Response;  import org.springframework.beans.factory.annotation.Autowired; @@ -42,16 +45,20 @@ import at.gv.egovernment.moa.id.auth.frontend.builder.IGUIFormBuilder;  import at.gv.egovernment.moa.id.auth.modules.AbstractAuthServletTask;  import at.gv.egovernment.moa.id.auth.modules.TaskExecutionException;  import at.gv.egovernment.moa.id.auth.modules.ssotransfer.SSOTransferConstants; +import at.gv.egovernment.moa.id.auth.modules.ssotransfer.data.SSOTransferContainer;  import at.gv.egovernment.moa.id.auth.modules.ssotransfer.utils.GUIUtils;  import at.gv.egovernment.moa.id.auth.modules.ssotransfer.utils.SSOContainerUtils;  import at.gv.egovernment.moa.id.commons.api.exceptions.MOAIDException;  import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException;  import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProviderFactory;  import at.gv.egovernment.moa.id.process.api.ExecutionContext; -import at.gv.egovernment.moa.id.protocols.pvp2x.config.PVPConfiguration; +import at.gv.egovernment.moa.id.protocols.pvp2x.PVPConstants; +import at.gv.egovernment.moa.id.protocols.pvp2x.utils.AssertionAttributeExtractor;  import at.gv.egovernment.moa.id.util.HTTPUtils;  import at.gv.egovernment.moa.logging.Logger; +import at.gv.egovernment.moa.util.Base64Utils;  import at.gv.egovernment.moa.util.MiscUtil; +import iaik.x509.X509Certificate;  /**   * @author tlenz @@ -100,6 +107,14 @@ public class RestoreSSOSessionTask extends AbstractAuthServletTask {  		} +    	String nonce = pendingReq.getGenericData(SSOTransferConstants.PENDINGREQ_NONCE, String.class); +    	SSOTransferContainer container = pendingReq.getGenericData( +    			SSOTransferConstants.PENDINGREQ_DH, SSOTransferContainer.class); +    	if (container == null) { +    		throw new TaskExecutionException(pendingReq, "NO DH-Params in pending-request", null); +    		 +    	} +    	  		if (MiscUtil.isNotEmpty(receivedPostMessage)) {  			Logger.debug("Receive POST-Message data. Start data-validation process ... "); @@ -109,40 +124,81 @@ public class RestoreSSOSessionTask extends AbstractAuthServletTask {  			    JsonObject reveivedSession = reveivedData.get("session").getAsJsonObject();  			    String validTo = reveivedSession.get("validTo").getAsString();  			    String entityID = reveivedSession.get("entityID").getAsString(); -			    String sessionBlob = reveivedSession.get("sessionBlob").getAsString(); +			    //String sessionBlob = reveivedSession.get("sessionBlob").getAsString(); +			   			     +//			    Logger.trace("Blob:" + sessionBlob +  +//			    			 " | validTo:" + validTo +  +//			    		     " | entityIS:" + entityID); +			    + +			    //TODO!!!! +			    String mobilePubKeyBase64 = reveivedSession.get( +						SSOTransferConstants.SSOCONTAINER_KEY_DH_PUBKEY).getAsString();	 +			    String encSessionBlobBase64 = new String(); -			    Logger.trace("Blob:" + sessionBlob +  -			    			 " | validTo:" + validTo +  -			    		     " | entityIS:" + entityID); +				Logger.debug("Receive PubKey:" +mobilePubKeyBase64 + " | SessionBlob:" + encSessionBlobBase64);  + +				//finish DH key agreement +				BigInteger mobilePubKey = new BigInteger(Base64Utils.decode(mobilePubKeyBase64, true)); +				DHPublicKeySpec mobilePubKeySpec = new DHPublicKeySpec(mobilePubKey,  +							container.getDhParams().getF().getP(),  +							container.getDhParams().getF().getG()); +				byte[] sharedSecret = ssoTransferUtils.getSecret(mobilePubKeySpec, container.getDhParams().getS()); +				 +				//build ASE256 key +				MessageDigest digest = MessageDigest.getInstance("SHA-256"); +				digest.reset(); +				byte[] hashedSecret = digest.digest(sharedSecret); +				 +				//decrypt CSR		 +				Logger.debug("Finished Diffie-Hellman key exchange.  --> Starting SessionBlob decryption ...");														 +				byte[] encryptedSessionBlob = Base64Utils.decode(encSessionBlobBase64, true);		 +				Logger.debug("EncSessionBlob:" + Base64Utils.encode(encryptedSessionBlob) + " | Key:" + Base64Utils.encode(hashedSecret)); +				 +				byte[] sessionBlobArray = ssoTransferUtils.enOrDeCryptCSR(encryptedSessionBlob, hashedSecret, Cipher.DECRYPT_MODE); +				String sessionBlob = new String(sessionBlobArray, "UTF-8"); +				Logger.debug("DecSessionBlob:" + sessionBlob);	 -			    if (PVPConfiguration.getInstance().getIDPPublicPath().contains(entityID)) { -			    	// stored SSO session data is from this IDP - start local session reconstruction -			    	Response ssoInformation = ssoTransferUtils.validateReceivedSSOContainer(sessionBlob, entityID); -			    				    	 -			    	//transfer SSO Assertion into MOA-Session -			    	ssoTransferUtils.parseSSOContainerToMOASessionDataObject(pendingReq, moasession, ssoInformation); -			    		 -			    	// store MOASession into database -					try { -						authenticatedSessionStorage.storeSession(moasession); -							 -					} catch (MOADatabaseException e) { -						Logger.error("Database Error! MOASession is not stored!"); -						throw new MOAIDException("init.04", new Object[] { -								moasession.getSessionID()}); -					} -			    		 -			    	executionContext.put(SSOTransferConstants.FLAG_SSO_SESSION_RESTORED, true); -			    	executionContext.put("sessionRestoreFinished", false);	 -			    					    				    	 -			    } else { -			    	Logger.info("Received SSO session-data is from IDP: " + entityID  -			    			+ ". Start inderfederation process to restore SSO session ... "); -			    	//change to inderfederated session reconstruction -			    	 -			    	Logger.warn("Device Session Transfer with interfederation is not implemented, yet!!!!"); +				//parse SAML2 assertion +				Response ssoInformation = ssoTransferUtils.validateReceivedSSOContainer(sessionBlob); +			    				 +				//validate signature +				AssertionAttributeExtractor attributeExtractor = new AssertionAttributeExtractor(ssoInformation); +				String holderOfKeyCertBase64 = attributeExtractor.getSingleAttributeValue(PVPConstants.PVP_HOLDEROFKEY_NAME); +				byte[] holderOfKeyCertEncoded = Base64Utils.decode(holderOfKeyCertBase64, false); +				X509Certificate holderOfKeyCert = new X509Certificate(holderOfKeyCertEncoded); +				Logger.debug("Found HolderOfKey Certificate:" + holderOfKeyCert.getSubjectDN().toString()); + +				 +				//TODO: implement Signature validation +				 +				Logger.debug("MobileDevice is valid. --> Starting session reconstruction ..."); +		    	 +				 +		    	//transfer SSO Assertion into MOA-Session +		    	ssoTransferUtils.parseSSOContainerToMOASessionDataObject(pendingReq, moasession, attributeExtractor); +		    		 +		    	// store MOASession into database +				try { +					authenticatedSessionStorage.storeSession(moasession); +						 +				} catch (MOADatabaseException e) { +					Logger.error("Database Error! MOASession is not stored!"); +					throw new MOAIDException("init.04", new Object[] { +							moasession.getSessionID()}); +				} +		    		 +		    	executionContext.put(SSOTransferConstants.FLAG_SSO_SESSION_RESTORED, true); +		    	executionContext.put("sessionRestoreFinished", false);	 +		    					    				    	 + +//		    	Logger.info("Received SSO session-data is from IDP: " + entityID  +//		    			+ ". Start inderfederation process to restore SSO session ... "); +//		    	//change to inderfederated session reconstruction +//		    	 +//		    	Logger.warn("Device Session Transfer with interfederation is not implemented, yet!!!!"); -			    } +  			 } catch (Exception e) {  				 Logger.error("Parse reveived JSON data-object " + sb.toString() + " FAILED!", e); @@ -171,7 +227,6 @@ public class RestoreSSOSessionTask extends AbstractAuthServletTask {  					Logger.debug("No restored SSO session found --> Wait a few minutes and check again.");  					executionContext.put("sessionRestoreFinished", false);	 -					VelocityContext context;  					try {  						//create first step of SSO Transfer GUI  						authURL = HTTPUtils.extractAuthURLFromRequest(request); @@ -183,7 +238,7 @@ public class RestoreSSOSessionTask extends AbstractAuthServletTask {  						}	  						GUIUtils.buildSSOTransferGUI(guiBuilder, response,  -								authURL, pendingReq.getRequestID()); +								authURL, pendingReq.getRequestID(), nonce, container.getDhParams().getF());  					} catch (IOException | MOAIDException e) {  						throw new TaskExecutionException(pendingReq, e.getMessage(), e); diff --git a/id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment/moa/id/auth/modules/ssotransfer/utils/GUIUtils.java b/id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment/moa/id/auth/modules/ssotransfer/utils/GUIUtils.java index b1446c4d2..13a278d1d 100644 --- a/id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment/moa/id/auth/modules/ssotransfer/utils/GUIUtils.java +++ b/id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment/moa/id/auth/modules/ssotransfer/utils/GUIUtils.java @@ -25,6 +25,7 @@ package at.gv.egovernment.moa.id.auth.modules.ssotransfer.utils;  import java.io.ByteArrayOutputStream;  import java.io.IOException; +import javax.crypto.spec.DHPublicKeySpec;  import javax.servlet.http.HttpServletResponse;  import com.google.gson.JsonObject; @@ -37,6 +38,7 @@ import at.gv.egovernment.moa.id.commons.MOAIDAuthConstants;  import at.gv.egovernment.moa.id.commons.api.exceptions.ConfigurationException;  import at.gv.egovernment.moa.logging.Logger;  import at.gv.egovernment.moa.util.Base64Utils; +import at.gv.egovernment.moa.util.MiscUtil;  import net.glxn.qrgen.QRCode;  import net.glxn.qrgen.image.ImageType; @@ -50,18 +52,50 @@ public class GUIUtils {  	public static void buildSSOTransferGUI(  			IGUIFormBuilder guiBuilder, HttpServletResponse httpResp,  			String authURL, String pendingReqID) throws ConfigurationException, IOException { +		buildSSOTransferGUI(guiBuilder, httpResp, authURL, pendingReqID, null, null); +				 +	} + +	/** +	 * @param guiBuilder +	 * @param response +	 * @param authURL +	 * @param requestID +	 * @param nonce +	 * @param dhKeyIDP +	 * @throws ConfigurationException  +	 * @throws IOException  +	 */ +	public static void buildSSOTransferGUI(IGUIFormBuilder guiBuilder, HttpServletResponse response, String authURL, +			String requestID, String nonce, DHPublicKeySpec dhKeyIDP) throws ConfigurationException, IOException {  		try {  			String containerURL = authURL  					+ SSOTransferConstants.SERVLET_SSOTRANSFER_FROM_SMARTPHONE -					+ "?" + MOAIDAuthConstants.PARAM_TARGET_PENDINGREQUESTID + "=" + pendingReqID; +					+ "?" + MOAIDAuthConstants.PARAM_TARGET_PENDINGREQUESTID + "=" + requestID; +			 +			 +			  			JsonObject qrResult = new JsonObject();  			qrResult.addProperty(SSOTransferConstants.SSOCONTAINER_KEY_TYPE,   					SSOTransferConstants.SSOCONTAINER_VALUE_TYPE_TRANSER);  			qrResult.addProperty(SSOTransferConstants.SSOCONTAINER_KEY_URL, containerURL); +			 +			if (MiscUtil.isNotEmpty(nonce)) +				qrResult.addProperty(SSOTransferConstants.SSOCONTAINER_KEY_NONCE, nonce); +			if (dhKeyIDP != null) { +				qrResult.addProperty(SSOTransferConstants.SSOCONTAINER_KEY_DH_PUBKEY,  +						Base64Utils.encode(dhKeyIDP.getY().toByteArray())); +				qrResult.addProperty(SSOTransferConstants.SSOCONTAINER_KEY_DH_PRIME,  +						Base64Utils.encode(dhKeyIDP.getP().toByteArray())); +				qrResult.addProperty(SSOTransferConstants.SSOCONTAINER_KEY_DH_GENERATOR,  +						Base64Utils.encode(dhKeyIDP.getG().toByteArray())); +				 +			} +			  			ByteArrayOutputStream qrStream =  -					QRCode.from(qrResult.toString()).to(ImageType.GIF).withSize(300, 300).stream();							 +					QRCode.from(qrResult.toString()).to(ImageType.GIF).withSize(350, 350).stream();							  			String base64EncodedImage = Base64Utils.encode(qrStream.toByteArray());  			DefaultGUIFormBuilderConfiguration config = new DefaultGUIFormBuilderConfiguration( @@ -74,13 +108,13 @@ public class GUIUtils {  			config.putCustomParameter("timeoutURL", containerURL);  			config.putCustomParameter("timeout", REFESH_TIMEOUT); -			guiBuilder.build(httpResp, config, "SSO-Transfer-Module"); +			guiBuilder.build(response, config, "SSO-Transfer-Module");  		} catch (GUIBuildException e) {  			Logger.warn("Can not build GUI:'BKU-Selection'. Msg:" + e.getMessage(), e);  			throw new ConfigurationException("builder.09", new Object[]{e.getMessage()}, e);  		} -				 +		  	}		  } diff --git a/id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment/moa/id/auth/modules/ssotransfer/utils/SSOContainerUtils.java b/id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment/moa/id/auth/modules/ssotransfer/utils/SSOContainerUtils.java index 9683d5cb7..ab0aba6a7 100644 --- a/id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment/moa/id/auth/modules/ssotransfer/utils/SSOContainerUtils.java +++ b/id/server/modules/moa-id-module-ssoTransfer/src/main/java/at/gv/egovernment/moa/id/auth/modules/ssotransfer/utils/SSOContainerUtils.java @@ -25,14 +25,31 @@ package at.gv.egovernment.moa.id.auth.modules.ssotransfer.utils;  import java.io.ByteArrayInputStream;  import java.io.IOException;  import java.io.StringWriter; +import java.math.BigInteger; +import java.security.InvalidKeyException; +import java.security.KeyFactory; +import java.security.KeyPair; +import java.security.KeyPairGenerator;  import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.PrivateKey; +import java.security.PublicKey;  import java.security.cert.CertificateException; +import java.security.spec.InvalidKeySpecException;  import java.util.ArrayList;  import java.util.Collections;  import java.util.Date;  import java.util.HashMap;  import java.util.List; +import javax.crypto.BadPaddingException; +import javax.crypto.Cipher; +import javax.crypto.IllegalBlockSizeException; +import javax.crypto.KeyAgreement; +import javax.crypto.NoSuchPaddingException; +import javax.crypto.spec.DHParameterSpec; +import javax.crypto.spec.DHPublicKeySpec; +import javax.crypto.spec.SecretKeySpec;  import javax.xml.XMLConstants;  import javax.xml.parsers.DocumentBuilder;  import javax.xml.parsers.DocumentBuilderFactory; @@ -83,6 +100,7 @@ import com.google.gson.JsonObject;  import at.gv.egovernment.moa.id.auth.data.AuthenticationSession;  import at.gv.egovernment.moa.id.auth.exception.ParseException;  import at.gv.egovernment.moa.id.auth.modules.ssotransfer.SSOTransferConstants; +import at.gv.egovernment.moa.id.auth.modules.ssotransfer.data.Pair;  import at.gv.egovernment.moa.id.auth.modules.ssotransfer.data.SSOTransferAuthenticationData;  import at.gv.egovernment.moa.id.auth.modules.ssotransfer.data.SSOTransferOnlineApplication;  import at.gv.egovernment.moa.id.auth.parser.IdentityLinkAssertionParser; @@ -149,8 +167,8 @@ public class SSOContainerUtils {  	@Autowired SAMLVerificationEngineSP samlVerificationEngine;  	@Autowired AuthConfiguration authConfig; -	public void parseSSOContainerToMOASessionDataObject(IRequest pendingReq, AuthenticationSession moasession, Response ssoInformation) throws AssertionAttributeExtractorExeption, ConfigurationException { -		AssertionAttributeExtractor attributeExtractor = new AssertionAttributeExtractor(ssoInformation); +	public void parseSSOContainerToMOASessionDataObject(IRequest pendingReq, AuthenticationSession moasession, AssertionAttributeExtractor attributeExtractor) throws AssertionAttributeExtractorExeption, ConfigurationException { +//		AssertionAttributeExtractor attributeExtractor = new AssertionAttributeExtractor(ssoInformation);  		//TODO: maybe change to correct URL  		//set dummy BKU URLx @@ -251,7 +269,7 @@ public class SSOContainerUtils {  	} -	public Response validateReceivedSSOContainer(String signedEncryptedContainer, String entityID) throws IOException, XMLParserException, UnmarshallingException, MOAIDException  { +	public Response validateReceivedSSOContainer(String signedEncryptedContainer) throws IOException, XMLParserException, UnmarshallingException, MOAIDException  {  		byte[] base64decodedContainer = Base64Utils.decode(signedEncryptedContainer, false);  		final BasicParserPool ppMgr = new BasicParserPool(); @@ -298,7 +316,7 @@ public class SSOContainerUtils {  				//validate PVP 2.1 assertion  				samlVerificationEngine.validateAssertion(ssoContainer, false,   						credentials.getIDPAssertionEncryptionCredential(), -						entityID, +						ssoContainer.getIssuer().getValue(),  						"SSO-Session Transfer module"  						);  				return ssoContainer; @@ -319,7 +337,7 @@ public class SSOContainerUtils {  	public String generateSignedAndEncryptedSSOContainer(String authURL, -			AuthenticationSession authSession, Date date) {		 +			AuthenticationSession authSession, Date date, byte[] hashedSecret) {		  		try {  			String entityID = PVPConfiguration.getInstance().getIDPSSOMetadataService(authURL);  			AuthnContextClassRef authnContextClassRef = SAML2Utils @@ -363,25 +381,68 @@ public class SSOContainerUtils {  			String ssoDataBlob = buildSSOContainerObject(authURL, assertion, new DateTime(date.getTime())); +			byte[] encPersonData = enOrDeCryptCSR(ssoDataBlob.getBytes(), hashedSecret, Cipher.ENCRYPT_MODE); +			String encAndEncodedPersonalData = Base64Utils.encode(encPersonData); + +			  			JsonObject container = new JsonObject();  			container.addProperty(SSOTransferConstants.SSOCONTAINER_KEY_TYPE, SSOTransferConstants.SSOCONTAINER_VALUE_TYPE_SSO);  			container.addProperty(SSOTransferConstants.SSOCONTAINER_KEY_VALIDTO, subjectConfirmationData.getNotOnOrAfter().toString());  			container.addProperty(SSOTransferConstants.SSOCONTAINER_KEY_ENTITYID, entityID);  			container.addProperty(SSOTransferConstants.SSOCONTAINER_KEY_USERID, authData.getGivenName() + " " + authData.getFamilyName()); -			container.addProperty(SSOTransferConstants.SSOCONTAINER_KEY_SESSION, ssoDataBlob); +			 +			container.addProperty(SSOTransferConstants.SSOCONTAINER_KEY_SESSION, encAndEncodedPersonalData);  			//TODO  			container.addProperty(SSOTransferConstants.SSOCONTAINER_KEY_RESULTENDPOINT, "https://demo.egiz.gv.at");  			return container.toString(); -		} catch (ConfigurationException | EncryptionException | CredentialsNotAvailableException | SecurityException | ParserConfigurationException | MarshallingException | SignatureException | TransformerFactoryConfigurationError | TransformerException | IOException e) { +		} catch (ConfigurationException | EncryptionException | CredentialsNotAvailableException | SecurityException | ParserConfigurationException | MarshallingException | SignatureException | TransformerFactoryConfigurationError | TransformerException | IOException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException | NoSuchAlgorithmException | NoSuchPaddingException e) {  			Logger.warn("SSO container generation FAILED.", e);  		}  		return null;  	} +	public byte[] enOrDeCryptCSR(byte[] binBlob, byte[] binSecret, int mode) throws IllegalBlockSizeException, BadPaddingException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException { +        byte[] decrypted = null; +        SecretKeySpec skeySpec = new SecretKeySpec(binSecret, "AES"); +        Cipher cipher = Cipher.getInstance("AES"); +        cipher.init(mode, skeySpec); +        decrypted = cipher.doFinal(binBlob); + +        return decrypted; +    } +	 +	public Pair<DHPublicKeySpec, PrivateKey> createSpecificKey(BigInteger p, BigInteger g) throws Exception { +		KeyPairGenerator kpg = KeyPairGenerator.getInstance("DiffieHellman"); + +		DHParameterSpec param = new DHParameterSpec(p, g); +		kpg.initialize(param); +		KeyPair kp = kpg.generateKeyPair(); + +		KeyFactory kfactory = KeyFactory.getInstance("DiffieHellman"); + +		Pair<DHPublicKeySpec, PrivateKey> pair = new Pair<DHPublicKeySpec, PrivateKey>( +		        (DHPublicKeySpec) kfactory.getKeySpec(kp.getPublic(), DHPublicKeySpec.class), kp.getPrivate()); +		return pair; + +	} +	 +	public byte[] getSecret(DHPublicKeySpec kspectrans, PrivateKey privateKey) throws NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException { +		KeyAgreement aKeyAgree = KeyAgreement.getInstance("DiffieHellman"); +		aKeyAgree.init(privateKey); +			 +		KeyFactory kfactory = KeyFactory.getInstance("DiffieHellman"); +		PublicKey pub = kfactory.generatePublic(kspectrans); +		aKeyAgree.doPhase(pub, true); +			 +		byte[] secretKey = aKeyAgree.generateSecret(); +		return secretKey; + +	} +	  	private String buildSSOContainerObject(String authURL, Assertion assertion, DateTime date) throws ConfigurationException, EncryptionException, CredentialsNotAvailableException, SecurityException, ParserConfigurationException, MarshallingException, SignatureException, TransformerFactoryConfigurationError, TransformerException, IOException {  		Response authResponse = SAML2Utils.createSAMLObject(Response.class); | 
