Răsfoiți Sursa

Addressed ISO 15118 User Group issue #50 (http://extmgmt.kn.e-technik.tu-dortmund.de/issues/50): the SECC will wait 5 seconds after sending a SessionStopRes or any response message with a negative response code before closing the TCP/TLS socket connection.

Also fixed an issue with reading the moSubCA2.pkcs8.der file (an encrypted private key which is provided in a PKCS#8 DER-encoded container.
Marc Mültin 6 ani în urmă
părinte
comite
693fbcc97a

+ 2 - 2
RISE-V2G-Certificates/generateCertificates.sh

@@ -225,8 +225,8 @@ openssl x509 -inform PEM -in certs/contractCert.pem    -outform DER -out certs/c
 
 
 # 17) In case you want the private keys in PKCS#8 file format and DER encoded, use this command. Especially necessary for the private key of MOSubCA2 in RISE V2G
-openssl pkcs8 -topk8 -in privateKeys/moSubCA2.key -inform PEM -passin file:passphrase.txt -passout file:passphrase.txt -outform DER -out privateKeys/moSubCA2.pkcs8.der
-
+openssl pkcs8 -topk8 -in privateKeys/moSubCA2.key -inform PEM -passin file:passphrase.txt -passout file:passphrase.txt -outform DER -out privateKeys/moSubCA2.pkcs8.der -v1 PBE-SHA1-3DES
+openssl pkcs8 -topk8 -in privateKeys/cpsSubCA2.key -inform PEM -passin file:passphrase.txt -passout file:passphrase.txt -outform DER -out privateKeys/cpsSubCA2.pkcs8.der -v1 PBE-SHA1-3DES
 
 # 18) Create the keystores for the EVCC and SECC. We need to first create the PKCS12 files and then import them into the JKS using the 'keytool' command.
 # 	- create a PKCS12 file -> -export

+ 8 - 0
RISE-V2G-SECC/src/main/java/com/v2gclarity/risev2g/secc/transportLayer/ConnectionHandler.java

@@ -169,6 +169,14 @@ public class ConnectionHandler extends Observable implements Runnable {
 	
 	
 	public void stop() {
+		// See ISO 15118 User Group issue http://extmgmt.kn.e-technik.tu-dortmund.de/issues/50
+		getLogger().debug("Waiting 5 seconds for EVCC to process response and close TCP/TLS connection ...");
+		try {
+            Thread.sleep(5000);
+        } catch (InterruptedException e) {
+            e.printStackTrace();
+        }
+		
 		if (!isStopAlreadyInitiated()) {
 			getLogger().debug("Closing connection to client ...");
 			setStopAlreadyInitiated(true);

+ 2 - 2
RISE-V2G-SECC/src/main/java/com/v2gclarity/risev2g/secc/transportLayer/TLSServer.java

@@ -129,10 +129,10 @@ public final class TLSServer extends StatefulTransportLayerServer {
 	@Override
 	public void stop() {
         try {
-        	getLogger().debug("TLS server will be stopped now");
+        		getLogger().debug("TLS server will be stopped now");
 			getTlsServerSocket().close();
         } catch (SocketException e) {
-        	getLogger().debug("TLSServerSocket was still active and has been closed now", e);
+        		getLogger().debug("TLSServerSocket was still active and has been closed now", e);
 		} catch (IOException e) {
 			getLogger().error("Error occurred while trying to close TLSServerSocket (IOException)", e);
 		}

+ 1 - 1
RISE-V2G-Shared/src/main/java/com/v2gclarity/risev2g/shared/misc/V2GCommunicationSession.java

@@ -112,7 +112,7 @@ public abstract class V2GCommunicationSession extends Observable {
 	 * but some other case causes a session termination
 	 * 
 	 * @param reason The termination cause
-	 * @param successful True, if in case of a successful session termination, false otherwise
+	 * @param successful True, in case of a successful session termination, false otherwise
 	 */
 	protected void terminateSession(String reason, boolean successful) {
 		String terminationPrefix = "Terminating V2G communication session, reason: "; 

+ 25 - 5
RISE-V2G-Shared/src/main/java/com/v2gclarity/risev2g/shared/utils/SecurityUtils.java

@@ -798,6 +798,15 @@ public final class SecurityUtils {
 	/**
 	 * Reads the private key from an encrypted PKCS#8 file and returns it as an ECPrivateKey instance.
 	 * 
+	 * ----- !! IMPORTANT NOTE!! -----
+	 * The PKCS#8 key file must be encrypted using a PKCS#12 encryption scheme, since JCE parsing of Pbes2Parameters (as defined in PKCS#5) 
+	 * is buggy in Java 1.8, see also https://bugs.openjdk.java.net/browse/JDK-8076999. The bug results in an IOException when trying to 
+	 * instantiate the EncryptedPrivateKeyInfo class.
+	 * 
+	 * The OpenSSL command used to create the DER-encoded and encrypted PKCS#8 file needs to use the 'v1 alg' option, specifying a proper algorithm. 
+	 * Example: '-v1 PBE-SHA1-3DES' (see https://www.openssl.org/docs/man1.0.2/man1/openssl-pkcs8.html).
+	 * -----
+	 * 
 	 * @param A PKCS#8 (.key) file containing the private key with value "s"
 	 * @return The private key as an ECPrivateKey instance
 	 */
@@ -808,19 +817,30 @@ public final class SecurityUtils {
 		try {
 			pkcs8ByteArray = Files.readAllBytes(fileLocation);
 			
-			// The DER encoded private key is password-based encrypted and provided in PKCS#8. So we need to decrypt it first
-			PBEKeySpec pbeKeySpec = new PBEKeySpec(GlobalValues.PASSPHRASE_FOR_CERTIFICATES_AND_KEYS.toString().toCharArray());
+			// Get the password that was used to encrypt the private key
+			PBEKeySpec password = new PBEKeySpec(GlobalValues.PASSPHRASE_FOR_CERTIFICATES_AND_KEYS.toString().toCharArray());
+			
+			// Read the ASN.1 structure of the PKCS#8 DER-encoded file
 		    EncryptedPrivateKeyInfo encryptedPrivKeyInfo = new EncryptedPrivateKeyInfo(pkcs8ByteArray);
+		    
+		    // Instantiate the key factory which will create the symmetric (secret) key using algorithm that is encoded in the ASN.1 structure 
+		    // (see 'v1 alg' in OpenSSL's pkcs8 command) and the given password
 		    SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance(encryptedPrivKeyInfo.getAlgName());
-		    Key secret = secretKeyFactory.generateSecret(pbeKeySpec);
-		    PKCS8EncodedKeySpec pkcs8PrivKeySpec = encryptedPrivKeyInfo.getKeySpec(secret);
-			
+		    
+		    // Create the symmetric key from the given password
+		    Key decryptKey = secretKeyFactory.generateSecret(password);
+		    
+		    // Extract the PKCS8EncodedKeySpec object from the encrypted data
+		    PKCS8EncodedKeySpec pkcs8PrivKeySpec = encryptedPrivKeyInfo.getKeySpec(decryptKey);
+		    
+		    // Generate the EC private key
 			ECPrivateKey privateKey = (ECPrivateKey) KeyFactory.getInstance("EC").generatePrivate(pkcs8PrivKeySpec);
 
 			return privateKey;
 		} catch (IOException | InvalidKeySpecException | NoSuchAlgorithmException | InvalidKeyException e) {
 			getLogger().error(e.getClass().getSimpleName() + " occurred while trying to access private key at " +
 					  "location '" + keyFilePath + "'");
+			e.printStackTrace();
 			return null;
 		} 
 	}