diff options
3 files changed, 98 insertions, 45 deletions
| 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 cc60bbd20..ce3a7856b 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 @@ -43,6 +43,7 @@ public class SSOTransferConstants {  	public static final String SSOCONTAINER_KEY_TYPE = "type";  	public static final String SSOCONTAINER_VALUE_TYPE_TRANSER = "TRANSFER";  	public static final String SSOCONTAINER_VALUE_TYPE_PERSIST = "PERSIST"; +	public static final String SSOCONTAINER_VALUE_TYPE_SSO = "SSO";  	public static final String SSOCONTAINER_KEY_URL = "url"; @@ -50,7 +51,7 @@ public class SSOTransferConstants {  	public static final String SSOCONTAINER_KEY_DH_PRIME = "prime";  	public static final String SSOCONTAINER_KEY_DH_GENERATOR = "generator"; -	public static final String SSOCONTAINER_KEY_CSR = "csr"; +	public static final String SSOCONTAINER_KEY_CSR = "certificate";  	public static final String SSOCONTAINER_KEY_VALIDTO = "validTo";  	public static final String SSOCONTAINER_KEY_ENTITYID = "entityID"; 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 80c2663fb..48ef5b526 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 @@ -33,6 +33,7 @@ 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; @@ -42,9 +43,14 @@ import java.security.spec.InvalidKeySpecException;  import java.security.spec.InvalidParameterSpecException;  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; @@ -182,7 +188,8 @@ public class SSOTransferServlet{  		Object tokenObj = req.getParameter(SSOTransferConstants.REQ_PARAM_TOKEN);		  		if (tokenObj != null && tokenObj instanceof String) {  			String token = (String)tokenObj; -			try {								 +			try { +				Logger.debug("Load token:" + token + " from storage.");  				SSOTransferContainer container = transactionStorage.get(token, SSOTransferContainer.class, transmisionTimeOut * 1000);  				if (container != null) {  					AuthenticationSession moaSession = new AuthenticationSession("123456", new Date()); @@ -213,51 +220,55 @@ public class SSOTransferServlet{  				resp.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Single Sign-On session transfer token is not valid any more.");  			} catch (OperatorCreationException e) { -				// TODO Auto-generated catch block -				e.printStackTrace(); +				Logger.warn("Device inpersonisation FAILED: " + e.getMessage(), e);  				resp.sendError(HttpServletResponse.SC_BAD_REQUEST, e.getMessage());  			} catch (CredentialsNotAvailableException e) { -				// TODO Auto-generated catch block -				e.printStackTrace(); +				Logger.warn("Device inpersonisation FAILED: " + e.getMessage(), e);  				resp.sendError(HttpServletResponse.SC_BAD_REQUEST, e.getMessage());  			} catch (PKCSException e) { -				// TODO Auto-generated catch block -				e.printStackTrace(); +				Logger.warn("Device inpersonisation FAILED: " + e.getMessage(), e);  				resp.sendError(HttpServletResponse.SC_BAD_REQUEST, e.getMessage());  			} catch (CertificateException e) { -				// TODO Auto-generated catch block -				e.printStackTrace(); +				Logger.warn("Device inpersonisation FAILED: " + e.getMessage(), e);  				resp.sendError(HttpServletResponse.SC_BAD_REQUEST, e.getMessage());  			} catch (InvalidKeyException e) { -				// TODO Auto-generated catch block -				e.printStackTrace(); +				Logger.warn("Device inpersonisation FAILED: " + e.getMessage(), e);  				resp.sendError(HttpServletResponse.SC_BAD_REQUEST, e.getMessage());  			} catch (NoSuchAlgorithmException e) { -				// TODO Auto-generated catch block -				e.printStackTrace(); +				Logger.warn("Device inpersonisation FAILED: " + e.getMessage(), e);  				resp.sendError(HttpServletResponse.SC_BAD_REQUEST, e.getMessage());  			} catch (InvalidKeySpecException e) { -				// TODO Auto-generated catch block -				e.printStackTrace(); +				Logger.warn("Device inpersonisation FAILED: " + e.getMessage(), e);  				resp.sendError(HttpServletResponse.SC_BAD_REQUEST, e.getMessage());  			} catch (SessionDataStorageException e) { -				// TODO Auto-generated catch block -				e.printStackTrace(); +				Logger.warn("Device inpersonisation FAILED: " + e.getMessage(), e);  				resp.sendError(HttpServletResponse.SC_BAD_REQUEST, e.getMessage()); +				  			} catch (ParseException e) { -				// TODO Auto-generated catch block -				e.printStackTrace(); +				Logger.warn("Device inpersonisation FAILED: " + e.getMessage(), e); +				resp.sendError(HttpServletResponse.SC_BAD_REQUEST, e.getMessage()); +				 +			} catch (IllegalBlockSizeException e) { +				Logger.warn("Device inpersonisation FAILED: " + e.getMessage(), e); +				resp.sendError(HttpServletResponse.SC_BAD_REQUEST, e.getMessage()); +				 +			} catch (BadPaddingException e) { +				Logger.warn("Device inpersonisation FAILED: " + e.getMessage(), e); +				resp.sendError(HttpServletResponse.SC_BAD_REQUEST, e.getMessage()); +				 +			} catch (NoSuchPaddingException e) { +				Logger.warn("Device inpersonisation FAILED: " + e.getMessage(), e); +				resp.sendError(HttpServletResponse.SC_BAD_REQUEST, e.getMessage()); +				  			} -			 -			 -		 +							  		} else {  			Logger.info("Servlet " + getClass().getName() + " receive a NOT valid request.");  			resp.sendError(HttpServletResponse.SC_NOT_FOUND, "Request not valid."); @@ -345,8 +356,17 @@ public class SSOTransferServlet{  				resp.sendError(HttpServletResponse.SC_BAD_REQUEST, e.getMessage());  			} catch (SessionDataStorageException e) { -				// TODO Auto-generated catch block  				e.printStackTrace(); +				resp.sendError(HttpServletResponse.SC_BAD_REQUEST, e.getMessage()); +			} catch (IllegalBlockSizeException e) { +				e.printStackTrace(); +				resp.sendError(HttpServletResponse.SC_BAD_REQUEST, e.getMessage()); +			} catch (BadPaddingException e) { +				e.printStackTrace(); +				resp.sendError(HttpServletResponse.SC_BAD_REQUEST, e.getMessage()); +			} catch (NoSuchPaddingException e) { +				e.printStackTrace(); +				resp.sendError(HttpServletResponse.SC_BAD_REQUEST, e.getMessage());  			} @@ -416,7 +436,8 @@ public class SSOTransferServlet{  	}  	private void internalTransferPersonalInformation(HttpServletRequest req, HttpServletResponse resp, -			SSOTransferContainer container, AuthenticationSession moaSession, boolean developmentMode) throws IOException, InvalidKeyException, NoSuchAlgorithmException, InvalidKeySpecException, OperatorCreationException, CredentialsNotAvailableException, PKCSException, CertificateException, SessionDataStorageException { +			SSOTransferContainer container, AuthenticationSession moaSession, boolean developmentMode) throws IOException, InvalidKeyException, NoSuchAlgorithmException, InvalidKeySpecException, OperatorCreationException, CredentialsNotAvailableException, PKCSException, CertificateException, SessionDataStorageException, IllegalBlockSizeException, BadPaddingException, NoSuchPaddingException { +		Logger.debug("");  		JsonObject receivedData = getJSONObjectFromPostMessage(req, developmentMode);  		if (receivedData == null) { @@ -424,33 +445,40 @@ public class SSOTransferServlet{  			throw new IOException("No data received");  		} -		  -		//TODO: check if needed -		//JsonObject reveivedSession = receivedData.get("session").getAsJsonObject(); -		 +				  		String mobilePubKeyBase64 = receivedData.get(  				SSOTransferConstants.SSOCONTAINER_KEY_DH_PUBKEY).getAsString();						  		String mobileCSRBase64 = receivedData.get(  				SSOTransferConstants.SSOCONTAINER_KEY_CSR).getAsString(); -		Logger.trace("Receive PubKey:" +mobilePubKeyBase64 +  -		  			 " | CSR:" + mobileCSRBase64);  +		Logger.debug("Receive PubKey:" +mobilePubKeyBase64 + " | CSR:" + mobileCSRBase64);   		//finish DH key agreement -		BigInteger mobilePubKey = new BigInteger(Base64Utils.decode(mobilePubKeyBase64, false)); +		BigInteger mobilePubKey = new BigInteger(Base64Utils.decode(mobilePubKeyBase64, true));  		DHPublicKeySpec mobilePubKeySpec = new DHPublicKeySpec(mobilePubKey,   					container.getDhParams().getF().getP(),   					container.getDhParams().getF().getG());  		byte[] sharedSecret = getSecret(mobilePubKeySpec, container.getDhParams().getS()); -		Logger.debug("Finished Diffie-Hellman key exchange.  --> Starting CSR decryption ...");												 -		//TODO decrypt CSR						 -		byte[] decryptedCSR = Base64Utils.decode(mobileCSRBase64, true); -			 +		//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 CSR decryption ...");														 +		byte[] encryptedCSR = Base64Utils.decode(mobileCSRBase64, true);		 +		Logger.debug("EncCSR:" + Base64Utils.encode(encryptedCSR) + " | Key:" + Base64Utils.encode(hashedSecret)); +		byte[] decryptedCSR = enOrDeCryptCSR(encryptedCSR, hashedSecret, Cipher.DECRYPT_MODE); +		Logger.debug("DecCSR:" + Base64Utils.encode(decryptedCSR));		 +		Logger.debug("CSR decryption finished. --> Starting CSR validation and signing ..."); +				  		//generate certificate from CSR  		X509Certificate mobileCert = signCSRWithMOAKey(decryptedCSR); +		Logger.debug("CSR validation finished. --> Starting personData generation ... "); +		  		moaSession.setGenericDataToSession(  				SSOTransferConstants.MOASESSION_DATA_HOLDEROFKEY_CERTIFICATE,   				mobileCert.getEncoded()); @@ -460,10 +488,17 @@ public class SSOTransferServlet{  		String personInformationToTransfer =   				ssoTransferUtils.generateSignedAndEncryptedSSOContainer(  						container.getAuthURL(), moaSession, now); -						 +		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(personInformationToTransfer); +		out.print(encAndEncodedPersonalData);  		out.flush();  		return; @@ -532,9 +567,19 @@ public class SSOTransferServlet{  	} -	private X509Certificate signCSRWithMOAKey(byte[] inputCSR) throws IOException, OperatorCreationException, PKCSException, CredentialsNotAvailableException, CertificateException { +	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); -		 +					  		//validate CSR request		  		ContentVerifierProvider verifier = new JcaContentVerifierProviderBuilder().setProvider(  				new BouncyCastleProvider()).build(csr.getSubjectPublicKeyInfo()); @@ -594,11 +639,12 @@ public class SSOTransferServlet{  		}  		JsonParser parser = new JsonParser(); -		JsonObject receivedData = null;		 -		if (MiscUtil.isNotEmpty(receivedPostMessage))					 +		JsonObject receivedData = null; +		Logger.debug("JSON POST msg: " + sb.toString());		 +		if (MiscUtil.isNotEmpty(receivedPostMessage)) {			  			receivedData = (JsonObject) parser.parse(sb.toString()); -		else if (developmentMode && MiscUtil.isNotEmpty(req.getParameter("blob"))) { +		} else if (developmentMode && MiscUtil.isNotEmpty(req.getParameter("blob"))) {  			receivedData = (JsonObject) parser.parse(req.getParameter("blob"));  		} 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 dea538f75..ddfd0958f 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 @@ -118,6 +118,10 @@ import iaik.x509.X509Certificate;   */  @Service("SSOContainerUtils")  public class SSOContainerUtils { +	 +	private static final String PVP_HOLDEROFKEY_NAME = PVPConstants.URN_OID_PREFIX +  +			"1.2.40.0.10.2.1.1.261.xx.xx"; +	      public static final List<String> REQUIRED_ATTRIBUTES;  	static {  		List<String> tmp = new ArrayList<String>(); @@ -133,7 +137,9 @@ public class SSOContainerUtils {  		tmp.add(PVPConstants.MANDATE_PROF_REP_OID_NAME);  		tmp.add(PVPConstants.MANDATE_PROF_REP_DESC_NAME);  		tmp.add(PVPConstants.EID_CITIZEN_QAA_LEVEL_NAME); -		tmp.add(PVPConstants.PVP_HOLDEROFKEY_NAME); +		 +		//TODO: change to final definition +		tmp.add(PVP_HOLDEROFKEY_NAME);          REQUIRED_ATTRIBUTES = Collections.unmodifiableList(tmp);  	} @@ -354,7 +360,7 @@ public class SSOContainerUtils {  			String ssoDataBlob = buildSSOContainerObject(authURL, assertion, new DateTime(date.getTime()));  			JsonObject container = new JsonObject(); -			container.addProperty(SSOTransferConstants.SSOCONTAINER_KEY_TYPE, "SSO"); +			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()); | 
