Hello,
Through several articles, I would like present the cryptographic mechanisms, types of keys, certificate, types of algorithms …etc:

 


Example, Use of SecretKey, PrivateKey, PublicKey, CSV file (CryptoTools, GenericObfuscationFile)
 

  1. GenericObfuscationFile
    GenericObfuscationFile is a generic utility class allowing the manipulations of CVS file composed of configurable number of columns containing obfuscated data and one key column. This class uses the Apache librairies commons-csv-x.y.jar (and commons-lang-a.b.jar). For example, the file could have the following structure:
    keyValue1,obfuscatedValue1-1,obfuscatedValue1-2
    keyValue2,obfuscatedValue2-1,obfuscatedValue2-2
    keyValue3,obfuscatedValue3-1,obfuscatedValue3-2
    keyValue4,obfuscatedValue4-1,obfuscatedValue4-2

     

    Here, the methods provided of GenericObfuscationFile:

    • GenericObfuscationFile(final File file, final int nbOfColumns, final int keyValueColumnIndex) : Constructor with 3 arguments : the target obfuscation file on filesystem, the total number of columns of this file and the index of key column (starting with 0). 
    • public boolean containsKeyValue(final String keyValue) : method checking the presence of key value in the CSV file. 
    • public boolean containsObfuscatedValue(final String obfuscatedValue) : method checking the presence of obfuscated value in whole file. 
    • public String getObfuscatedValue(final int indexOfColumn, final String keyValue) : method allowing the getting the obfuscated value from the key value. 
    • public String getKeyValue(final int indexOfColumn, final String obfuscatedValue) : method allowing the getting the key value from the obfuscated value. 
    • public synchronized void add(final String keyValue, String… obfuscatedValues) : method adding a new line in the obfuscation file (key value, obfuscated values). 
    • public File exportToOtherFile(final File targetFile) : method allowing the exportation of manipulated data to other obfuscation file. 
    • public boolean hasChanges() : method specifying if the data have been changed since their loading. 

     
    In order to illustrate the use of this class GenericObfuscationFile, below some tests on a file composed of 3 columns whose the first column is the key value column (see GenericObfuscationFileTest):

        private static final String FIRST_KEY_VALUE = "KEY-1";
        private static final String FIRST_OBFUSCATED_VALUE_IN_COL1 = "OBFUSCATED-1-1";
        private static final String FIRST_OBFUSCATED_VALUE_IN_COL2 = "OBFUSCATED-1-2";
        private static final String SECOND_KEY_VALUE = "KEY-2";
        private static final String SECOND_OBFUSCATED_VALUE_IN_COL1 = "OBFUSCATED-2-1";
        private static final String SECOND_OBFUSCATED_VALUE_IN_COL2 = "OBFUSCATED-2-2";
        //
        private static final int NB_OF_COLUMNS = 3;
        private static final int INDEX_OF_COLUMN_KEY = 0;
        private static final int INDEX_OF_COLUMN_OBFUSCATED_VALUE_1 = 1;
        private static final int INDEX_OF_COLUMN_OBFUSCATED_VALUE_2 = 2;
        
        private static File temporaryFile = null;
        private static GenericObfuscationFile obfuscationFile = null;
        
        public static void main(String[] args) {
        	GenericObfuscationFileTest me = null;
        	try{
            	me = new GenericObfuscationFileTest();
            	me.beforeTests();
            	me.test_01_createObfuscationFileFromEmptyFile();
            	me.test_02_addFirstObfuscationEntry();
                try{
                    me.test_03_addDuplicatedObfuscatedInColumn2Value();
                }catch(IllegalArgumentException expected){
                	System.out.println("IllegalArgumentException expected : " + expected.getMessage());
                }
                try{
                    me.test_04_addDuplicatedObfuscatedValue();
                }catch(IllegalArgumentException expected){
                	System.out.println("IllegalArgumentException expected : " + expected.getMessage());
                }
            	me.test_05_addSecondObfuscationEntry();
            	me.test_06_createObfuscationFileNonEmptyFromFile();
            	me.test_07_exportToOtherFile();
        	}catch(Throwable th){
        		th.printStackTrace();
        	}finally{
        		if(me!=null){
            		me.afterTests();
        		}
        	}
        }
    
        public void beforeTests() throws Throwable {
            temporaryFile = getTempFile();
        }
    
        public void afterTests() {
            remove(temporaryFile);
        }
    
        private File getTempFile() throws Throwable {
    	try {
    		final File tempFile = File.createTempFile("file-for-testing", null);
    		Assert.assertNotNull(tempFile);
    		tempFile.deleteOnExit();
    		return tempFile;
    	} catch (final IOException ioe) {
    		throw new RuntimeException(ioe);
    	}
        }
    	
        private void remove(final File file) {
    	if (file != null && file.exists()) {
    		file.delete();
    	}
        }
    

     

    • test_01_createObfuscationFileFromEmptyFile() :
      …Java code:

      System.out.println("----------------- test_01_createObfuscationFileFromEmptyFile(...)");
      
      obfuscationFile = new GenericObfuscationFile(temporaryFile, NB_OF_COLUMNS, INDEX_OF_COLUMN_KEY);
      
      Assert.assertNotNull(obfuscationFile);
      
      Assert.assertFalse(obfuscationFile.hasChanges());
      

      …outputs:
      ----------------- test_01_createObfuscationFileFromEmptyFile(...)
      Loading existing obfuscated values from 'C:\Users\H\AppData\Local\Temp\file-for-testing6583113437465951042.tmp'

      …file’s contents (file-for-testing6583113437465951042.tmp):


       

    • test_02_addFirstObfuscationEntry() :
      …Java code:

      System.out.println("----------------- test_02_addFirstObfuscationEntry(...)");
      
      // Add a first entry
      Assert.assertFalse(obfuscationFile.containsKeyValue(FIRST_KEY_VALUE));
      
      obfuscationFile.add(FIRST_KEY_VALUE, FIRST_OBFUSCATED_VALUE_IN_COL1, FIRST_OBFUSCATED_VALUE_IN_COL2);
      
      Assert.assertTrue(obfuscationFile.containsKeyValue(FIRST_KEY_VALUE));
      
      Assert.assertEquals(FIRST_OBFUSCATED_VALUE_IN_COL1, obfuscationFile.getObfuscatedValue(INDEX_OF_COLUMN_OBFUSCATED_VALUE_1, FIRST_KEY_VALUE));
      
      Assert.assertEquals(FIRST_OBFUSCATED_VALUE_IN_COL2, obfuscationFile.getObfuscatedValue(INDEX_OF_COLUMN_OBFUSCATED_VALUE_2, FIRST_KEY_VALUE));
      
      Assert.assertEquals(FIRST_KEY_VALUE, obfuscationFile.getKeyValue(INDEX_OF_COLUMN_OBFUSCATED_VALUE_1, FIRST_OBFUSCATED_VALUE_IN_COL1));
      
      Assert.assertEquals(FIRST_KEY_VALUE, obfuscationFile.getKeyValue(INDEX_OF_COLUMN_OBFUSCATED_VALUE_2, FIRST_OBFUSCATED_VALUE_IN_COL2));
      
      Assert.assertTrue(obfuscationFile.hasChanges());
      
      // Check persisted information in file
      Scanner scanner = null;
      try {
            scanner = new Scanner(temporaryFile);
            Assert.assertTrue(scanner.hasNext());
            final String persistedLine = scanner.nextLine();
            Assert.assertNotNull(persistedLine);
            Assert.assertArrayEquals(new String[]{ FIRST_KEY_VALUE, FIRST_OBFUSCATED_VALUE_IN_COL1, FIRST_OBFUSCATED_VALUE_IN_COL2 }, persistedLine.split(GenericObfuscationFile.FIELD_SEPARATOR));
            Assert.assertFalse(scanner.hasNext());
      } finally {
            if (scanner != null) {
                  scanner.close();
            }
      }
      

      …outputs:
      ----------------- test_02_addFirstObfuscationEntry(...)
      Add new line to 'C:\Users\H\AppData\Local\Temp\file-for-testing6583113437465951042.tmp'

      …file’s contents (file-for-testing6583113437465951042.tmp):
      KEY-1,OBFUSCATED-1-1,OBFUSCATED-1-2

       

    • test_03_addDuplicatedObfuscatedInColumn2Value() :
      …Java code:

      System.out.println("----------------- test_03_addDuplicatedObfuscatedInColumn2Value(...)");
      
      obfuscationFile.add(FIRST_KEY_VALUE, "xxxxxx", "xxxxxx");
      

      …outputs:
      ----------------- test_03_addDuplicatedObfuscatedInColumn2Value(...)
      IllegalArgumentException expected : Obfuscation file already contains an obfuscated value for this key value (KEY-1)

      …file’s contents (file-for-testing6583113437465951042.tmp):
      KEY-1,OBFUSCATED-1-1,OBFUSCATED-1-2

       

    • test_04_addDuplicatedObfuscatedValue() :
      …Java code:

      System.out.println("----------------- test_04_addDuplicatedObfuscatedValue(...)");
      
      obfuscationFile.add("xxxxxx", FIRST_OBFUSCATED_VALUE_IN_COL1, "xxxxxx");
      

      …outputs:
      ----------------- test_04_addDuplicatedObfuscatedValue(...)
      IllegalArgumentException expected : Obfuscation file already contains an obfuscated value (OBFUSCATED-1-1) for another key value

      …file’s contents (file-for-testing6583113437465951042.tmp):
      KEY-1,OBFUSCATED-1-1,OBFUSCATED-1-2

       

    • test_05_addSecondObfuscationEntry() :
      …Java code:

      System.out.println("----------------- test_05_addSecondObfuscationEntry(...)");
      
      // Add a second entry
      Assert.assertFalse(obfuscationFile.containsKeyValue(SECOND_KEY_VALUE));
      
      obfuscationFile.add(SECOND_KEY_VALUE, SECOND_OBFUSCATED_VALUE_IN_COL1, SECOND_OBFUSCATED_VALUE_IN_COL2);
      
      Assert.assertTrue(obfuscationFile.containsKeyValue(SECOND_KEY_VALUE));
      
      Assert.assertEquals(SECOND_OBFUSCATED_VALUE_IN_COL1, obfuscationFile.getObfuscatedValue(INDEX_OF_COLUMN_OBFUSCATED_VALUE_1, SECOND_KEY_VALUE));
      
      Assert.assertEquals(SECOND_OBFUSCATED_VALUE_IN_COL2, obfuscationFile.getObfuscatedValue(INDEX_OF_COLUMN_OBFUSCATED_VALUE_2, SECOND_KEY_VALUE));
      
      Assert.assertEquals(SECOND_KEY_VALUE, obfuscationFile.getKeyValue(INDEX_OF_COLUMN_OBFUSCATED_VALUE_1, SECOND_OBFUSCATED_VALUE_IN_COL1));
      
      Assert.assertEquals(SECOND_KEY_VALUE, obfuscationFile.getKeyValue(INDEX_OF_COLUMN_OBFUSCATED_VALUE_2, SECOND_OBFUSCATED_VALUE_IN_COL2));
      
      Assert.assertTrue(obfuscationFile.hasChanges());
      
      // Check persisted information in file
      Scanner scanner = null;
      try {
            scanner = new Scanner(temporaryFile);
            Assert.assertTrue(scanner.hasNext());
            scanner.nextLine(); // LINE 1 
            Assert.assertTrue(scanner.hasNext());  
            final String persistedLine = scanner.nextLine(); // LINE 2
            Assert.assertNotNull(persistedLine);
            Assert.assertArrayEquals(new String[]{ SECOND_KEY_VALUE, SECOND_OBFUSCATED_VALUE_IN_COL1, SECOND_OBFUSCATED_VALUE_IN_COL2 }, persistedLine.split(GenericObfuscationFile.FIELD_SEPARATOR));
            Assert.assertFalse(scanner.hasNext());
      } finally {
            if (scanner != null) {
                  scanner.close();
            }
      }
      

      …outputs:
      ----------------- test_05_addSecondObfuscationEntry(...)
      Add new line to 'C:\Users\H\AppData\Local\Temp\file-for-testing6583113437465951042.tmp'

      …file’s contents (file-for-testing6583113437465951042.tmp):
      KEY-1,OBFUSCATED-1-1,OBFUSCATED-1-2
      KEY-2,OBFUSCATED-2-1,OBFUSCATED-2-2

       

    • test_06_createObfuscationFileNonEmptyFromFile() :
      …Java code:

      System.out.println("----------------- test_06_createObfuscationFileNonEmptyFromFile(...)");
      
      obfuscationFile = new GenericObfuscationFile(temporaryFile, NB_OF_COLUMNS, INDEX_OF_COLUMN_KEY);
      
      Assert.assertNotNull(obfuscationFile);
      
      Assert.assertEquals(FIRST_OBFUSCATED_VALUE_IN_COL1, obfuscationFile.getObfuscatedValue(1, FIRST_KEY_VALUE));
      
      Assert.assertEquals(SECOND_OBFUSCATED_VALUE_IN_COL1, obfuscationFile.getObfuscatedValue(1, SECOND_KEY_VALUE));
      
      Assert.assertFalse(obfuscationFile.hasChanges());
      

      …outputs:
      ----------------- test_06_createObfuscationFileNonEmptyFromFile(...)
      Loading existing obfuscated values from 'C:\Users\H\AppData\Local\Temp\file-for-testing6583113437465951042.tmp'

      …file’s contents (file-for-testing6583113437465951042.tmp):
      KEY-1,OBFUSCATED-1-1,OBFUSCATED-1-2
      KEY-2,OBFUSCATED-2-1,OBFUSCATED-2-2

       

    • test_07_exportToOtherFile() :
      …Java code:

      System.out.println("----------------- test_07_exportToOtherFile(...)");
      
      Scanner scanner = null;
      
      File exportedFile = new File(new File(System.getProperty("java.io.tmpdir")), String.format("other_data_file_%tF.txt", new Date()));
      
      final File resultFile = obfuscationFile.exportToOtherFile(exportedFile);
      
      try {
              // Check persisted information in file
              scanner = new Scanner(resultFile);
              Assert.assertTrue(scanner.hasNext());
      
              String persistedLine = scanner.nextLine();
              Assert.assertNotNull(persistedLine);
              Assert.assertArrayEquals(new String[]{ FIRST_KEY_VALUE, FIRST_OBFUSCATED_VALUE_IN_COL1, FIRST_OBFUSCATED_VALUE_IN_COL2 }, persistedLine.split(GenericObfuscationFile.FIELD_SEPARATOR));
              Assert.assertTrue(scanner.hasNext());
      
              persistedLine = scanner.nextLine();
              Assert.assertNotNull(persistedLine);
              Assert.assertArrayEquals(new String[]{ SECOND_KEY_VALUE, SECOND_OBFUSCATED_VALUE_IN_COL1, SECOND_OBFUSCATED_VALUE_IN_COL2 }, persistedLine.split(GenericObfuscationFile.FIELD_SEPARATOR));
              Assert.assertFalse(scanner.hasNext());
      } finally {
              if (scanner != null) {
                      scanner.close();
              }
              remove(resultFile);
      }
      

      …outputs:
      ----------------- test_07_exportToOtherFile(...)
      Export all 2 lines, 3 columns to 'C:\Users\H\AppData\Local\Temp\other_data_file_2017-02-01.txt' (0 newly added values)

      …file’s contents (file-for-testing6583113437465951042.tmp):
      KEY-1,OBFUSCATED-1-1,OBFUSCATED-1-2
      KEY-2,OBFUSCATED-2-1,OBFUSCATED-2-2

      …file’s contents (other_data_file_2017-02-01.txt):
      KEY-1,OBFUSCATED-1-1,OBFUSCATED-1-2
      KEY-2,OBFUSCATED-2-1,OBFUSCATED-2-2

       

  2.  


     

  3. CryptoTools
    CryptoTools is an cryptography tools using a secret, private, public keys and providing several methods in order to:

    • Obfuscate a value that should be send to another system
    • Illuminate a previously obfuscated value
    • Decipher a ciphered input stream and write the readable result in the provided output stream
    • Decipher file content
    • Decipher a input stream content
    • Decipher a ciphered file and write the readable result in the provided file
    • Cipher a readable file and write the ciphered result in the provided ciphered file
    • Cipher a input stream content and return the result as a byte array
    • Cipher an input stream content to the provided output stream

    This class uses the Apache librairies commons-io-x.y.jar and com.ho.crypto.test3.encryption.base64.Base64Url exposed in the post Encoding with base64, base64url, rfc-4648.
    The hexa format is more adapted than base64 because base64 generates multiple lines that is not compatible with a CSV file format.

    private final static String RSA_ALGO = "RSA/ECB/PKCS1Padding";
    private final static String AES_ECB_ALGO = "AES/ECB/PKCS5Padding";
    private final static String DIGEST_ALGO = "SHA-1";
    //
    private final static String AES_CBC_ALGO = "AES/CBC/PKCS5Padding";
    private static final int IV_LENGTH = 16;
    

    Here, the methods provided of CryptoTools:

    • public String obfuscate_With_AesEcbSecret_Hexa(Key secretKey, final String value) : method obfuscating a string via the following steps:
      * 1. the AES/ECB/PKCS5Padding encryption via symetric secret key provided in parameter,
      * 2. the HEXA conversion allowing to obtain a result with strandard ANSI charachters (0-9,A-F)
      => Return the same obfuscated result for the same source
       
    • String obfuscate_With_RSAPublic_SHA1_BASE64(PublicKey publicKey, final String value) : method obfuscating a string via the following steps:
      * 1. the RSA/ECB/PKCS1Padding encryption via asymetric public key provided in parameter,
      * 2. the SHA-1 hash generation in order to forbid the reversibility (max length is 27 bytes)
      * 3. the BASE64 transformation allowing to obtain a result with strandard charachters
      => Don’t return the same obfuscated result for the same source

      Important note : The RSA encryption has a limitation linked to key’s length. For example, in our case, the size of RSA key’s length being 1024 bits / 128 bytes (1024/8), the max length of data to encrypt will be 128 – 11 = 117 bytes. If the length of data to encrypt is superior to 117 bytes, the encryption is going to throw a “javax.crypto.IllegalBlockSizeException: Data must not be longer than 117 bytes”.
       

    • String obfuscate_With_RSAPublic_Hexa(PublicKey publicKey, final String value) : method obfuscating a string via the following steps:
      * 1. the RSA/ECB/PKCS1Padding encryption via asymetric public key provided in parameter,
      * 2. the HEXA conversion allowing to obtain a result with strandard ANSI charachters (0-9,A-F)
      => Doesn’t return the same obfuscated result for the same source
       
    • public String illuminate_With_Hexa_RSAPrivate(PrivateKey privateKey, final String value) : method illuminating an obfuscated string via the following steps:
      * 1. the HEXA reverse-conversion,
      * 2. the RSA/ECB/PKCS1Padding decryption via asymetric private key provided in parameter,
      => Return the same illuminated result for different obfuscated value of the same original source
       
    • public String illuminate_With_Hexa_AesEcbSecret(Key secretKey, final String value) : method illuminating an obfuscated string via the following steps:
      * 1. the HEXA reverse-conversion,
      * 2. the AES/ECB/PKCS5Padding decryption via symetric secret key provided in parameter,
      => Return the same illuminated result for the same obfuscated value
       
    • public void encrypt_With_AesCbcSecret(Key secretKey, final InputStream is, final OutputStream os) : method encrypting a string via the following steps:
      * 1. the creation of a random initialization vector needed for the encryption
      * 2. the AES/CBC/PKCS5Padding encryption via symetric secret key provided in parameter,
       
    • public void decryptStream_With_AesCbcSecret(Key secretKey, final InputStream is, final OutputStream os) : method decrypting a string via the following steps:
      * 1. the reading of the random initialization vector needed for the decryption
      * 2. the AES/CBC/PKCS5Padding decryption via symetric secret key provided in parameter,
       

     

    In order to demonstrate these usefulity of these methods, below some tests (see CryptoToolsTest):
    …first, the generation of PublicKey, PrivateKey (RSA 1024 bits) and SecretKey (AES 128 bits):

    	private static PublicKey publicKey = null;
    	private static PrivateKey privateKey = null;
    	private static Key secretKey = null;
    	static{
    		try{
            	KeyGenerator keyGenAes = KeyGenerator.getInstance("AES");
        		keyGenAes.init(128); // 128 bits
        		secretKey = keyGenAes.generateKey();
        		//
    	   		KeyPairGenerator keyGenRsa = KeyPairGenerator.getInstance("RSA");
    	   		keyGenRsa.initialize(1024); // 1024 bits
    	   		KeyPair keyPair = keyGenRsa.genKeyPair();
    	   		publicKey = keyPair.getPublic();
    	   		privateKey = keyPair.getPrivate();
    		}catch(Throwable th){
    			th.printStackTrace();
    	    }
    	}
    
    
        private static CryptoTools cryptoTools;
    
        public static void main(String[] args) {
        	CryptoToolsTest me = null;
        	try{
            	me = new CryptoToolsTest();
            	me.beforeTests();
            	
                String readableMessage = "Hello beautiful pink unicorn !!!";
            	me.test_01_obfuscateString_With_AesEcbSecret_Hexa(readableMessage);
            	me.test_02_obfuscateString_With_RSAPublic_Hexa(readableMessage);
            	me.test_03_obfuscateString_With_RSAPublic_SHA1_BASE64(readableMessage);
            	
            	try{
            		// Caused by: javax.crypto.IllegalBlockSizeException: Data must not be longer than 117 bytes
                	me.test_04_obfuscateStringOfXxxxXChars_With_RSAPublic_SHA1_BASE64(118);
                	Assert.assertTrue(false); // Normally, this point must not be UNreachable
            	}catch(javax.crypto.IllegalBlockSizeException excIgnore){
                	Assert.assertTrue(true); // Normally, this exception is OK
            		System.out.println("obfuscateStringOfXxxxXChars(118) -> IllegalBlockSizeException : OK");
            	}
    
            	me.test_04_obfuscateStringOfXxxxXChars_With_RSAPublic_SHA1_BASE64(117);
            	
            	me.test_05_cipherAndDecipherContent_With_AesCbc();
            	
            	me.test_06_cipherAndDecipherFile_With_AesCbc();
        	
        	}catch(Throwable th){
        		th.printStackTrace();
        	}finally{
        		if(me!=null){
            		me.afterTests();
        		}
        	}
        }
        
        public void beforeTests() throws Throwable {
            cryptoTools = new CryptoTools();
        }
    
        public void afterTests() {
        }
    
        //--------------------------------------------------------------------------------- private methods
        private InputStream getResourceStream(final String fileName) throws Throwable{
    		final InputStream is = new FileInputStream(fileName);
    		Assert.assertNotNull("Cannot load '" + fileName + "'", is);
    		return is;
    	}
    
    	private File getTempFile() throws Throwable {
    		try {
    			final File tempFile = File.createTempFile("file-for-testing", null);
    			Assert.assertNotNull(tempFile);
    			tempFile.deleteOnExit();
    			return tempFile;
    		} catch (final IOException ioe) {
    			throw new RuntimeException(ioe);
    		}
    	}
    	
    	private void remove(final File file) {
    		if (file != null && file.exists()) {
    			file.delete();
    		}
    	}
    	
    	private byte[] readFully(final File file) throws Throwable {
    		try {
                return readFully(new FileInputStream(file));
    		} catch (Exception e) {
    			throw new RuntimeException("Cannot read file '" + file.getAbsolutePath() + "'", e);
    		}
    	}
    
    	private byte[] readFully(final InputStream is) throws Throwable {
            try {
                final ByteArrayOutputStream baos = new ByteArrayOutputStream();
                IOUtils.copy(is, baos);
                return baos.toByteArray();
            } catch (Exception e) {
                throw new RuntimeException("Cannot read stream", e);
            } finally {
                IOUtils.closeQuietly(is);
            }
        }
    
        private boolean equals(final File file1, final File file2) throws Throwable {
            final byte[] content1 = readFully(new FileInputStream(file1));
            final byte[] content2 = readFully(new FileInputStream(file2));
            return Arrays.equals(content1, content2);
        }
    
        private Date today() {
            return new Date();
        }
    
        private Date yesterday() {
            return DateUtils.truncate(DateUtils.addDays(new Date(), -1), Calendar.DATE);
        }
    

     

    • test_01_obfuscateString_With_AesEcbSecret_Hexa(String readableMessage) :
      …Java code:

      System.out.println("----------------- test_01_obfuscateString_With_AesEcbSecret_Hexa(...)");
      final String obfuscatedValue = cryptoTools.obfuscate_With_AesEcbSecret_Hexa(secretKey, readableMessage);
      Assert.assertNotNull(obfuscatedValue);
      Assert.assertNotEquals("Obfuscation result should be different than original string", readableMessage, obfuscatedValue);
      
      // Return the same obfuscated result for the same source
      final String newObfuscatedValue = cryptoTools.obfuscate_With_AesEcbSecret_Hexa(secretKey, readableMessage);
      Assert.assertEquals("Obfuscation of a same value should return the same result", obfuscatedValue, newObfuscatedValue);
      
      // Return the same illuminated result for the same obfuscated value
      final String illuminatedValue = cryptoTools.illuminate_With_Hexa_AesEcbSecret(secretKey, obfuscatedValue);
      Assert.assertEquals("Illuminated value should return the original value", readableMessage, illuminatedValue);
      final String newIlluminatedValue = cryptoTools.illuminate_With_Hexa_AesEcbSecret(secretKey, newObfuscatedValue);
      Assert.assertEquals("Illuminated values of obfuscated values should return the same result (source)", illuminatedValue, newIlluminatedValue);
      

      …outputs:
      ----------------- test_01_obfuscateString_With_AesEcbSecret_Hexa(...)
      ----- FUNCTION : obfuscate_With_AesEcbSecret_Hexa - START
      - STEP 1 : Encrypt 'Hello beautiful pink unicorn !!!' with 'AES/ECB/PKCS5Padding' symmetric algo (secretKey)
      - STEP 1 : Done => 'ê­ÏVup9N‘ð—ßBžkÊ4½î‹ôVœÈ· ?±mÁ'
      - STEP 2 : Convert to hexa representation
      - STEP 2 : Done => 'EAAD00CF567570394E91F0029707DF429E6BCA34BDEE8BF4569CC804B70C3FB16DC100D3047A8369E316A783F37CAC3E'
      - RESULT = 'Hello beautiful pink unicorn !!!' obfuscated to 'EAAD00CF567570394E91F0029707DF429E6BCA34BDEE8BF4569CC804B70C3FB16DC100D3047A8369E316A783F37CAC3E'
      ----- FUNCTION : obfuscate_With_AesEcbSecret_Hexa - END

      ----- FUNCTION : obfuscate_With_AesEcbSecret_Hexa - START
      - STEP 1 : Encrypt 'Hello beautiful pink unicorn !!!' with 'AES/ECB/PKCS5Padding' symmetric algo (secretKey)
      - STEP 1 : Done => 'ê­ÏVup9N‘ð—ßBžkÊ4½î‹ôVœÈ· ?±mÁ'
      - STEP 2 : Convert to hexa representation
      - STEP 2 : Done => 'EAAD00CF567570394E91F0029707DF429E6BCA34BDEE8BF4569CC804B70C3FB16DC100D3047A8369E316A783F37CAC3E'
      - RESULT = 'Hello beautiful pink unicorn !!!' obfuscated to 'EAAD00CF567570394E91F0029707DF429E6BCA34BDEE8BF4569CC804B70C3FB16DC100D3047A8369E316A783F37CAC3E'
      ----- FUNCTION : obfuscate_With_AesEcbSecret_Hexa - END

      ----- FUNCTION : illuminate_With_Hexa_AesEcbSecret - START
      - STEP 1 : Convert from hexa representation
      - STEP 1 : Done => 'ê­ÏVup9N‘ð—ßBžkÊ4½î‹ôVœÈ· ?±mÁ'
      - STEP 2 : Encrypt with 'RSA/ECB/PKCS1Padding' symmetric algo (secretKey)
      - STEP 2 : Done => 'Hello beautiful pink unicorn !!!'
      ----- FUNCTION : illuminate_With_Hexa_AesEcbSecret - END

      ----- FUNCTION : illuminate_With_Hexa_AesEcbSecret - START
      - STEP 1 : Convert from hexa representation
      - STEP 1 : Done => 'ê­ÏVup9N‘ð—ßBžkÊ4½î‹ôVœÈ· ?±mÁ'
      - STEP 2 : Encrypt with 'RSA/ECB/PKCS1Padding' symmetric algo (secretKey)
      - STEP 2 : Done => 'Hello beautiful pink unicorn !!!'
      ----- FUNCTION : illuminate_With_Hexa_AesEcbSecret - END

       

    • test_02_obfuscateString_With_RSAPublic_Hexa(String readableMessage) :
      …Java code:

      System.out.println("----------------- test_02_obfuscateString_With_RSAPublic_Hexa(...)");
      final String obfuscatedValue = cryptoTools.obfuscate_With_RSAPublic_Hexa(publicKey, readableMessage);
      Assert.assertNotNull(obfuscatedValue);
      Assert.assertNotEquals("Obfuscation result should be different than original string", readableMessage, obfuscatedValue);
      
      // Don't return the same obfuscated result for the same source
      final String newObfuscatedValue = cryptoTools.obfuscate_With_RSAPublic_Hexa(publicKey, readableMessage);
      Assert.assertNotEquals("Obfuscation of a same value should return different result", obfuscatedValue, newObfuscatedValue);
      
      // Return the same illuminated result for different obfuscated value of the same original source
      final String illuminatedValue = cryptoTools.illuminate_With_Hexa_RSAPrivate(privateKey, obfuscatedValue);
      Assert.assertEquals("Illuminated value should return the original value", readableMessage, illuminatedValue);
      final String newIlluminatedValue = cryptoTools.illuminate_With_Hexa_RSAPrivate(privateKey, newObfuscatedValue);
      Assert.assertEquals("Illuminated values of different obfuscated values of a same source value should return the same result (source)", illuminatedValue, newIlluminatedValue);
      

      …outputs:
      ----------------- test_02_obfuscateString_With_RSAPublic_Hexa(...)
      ----- FUNCTION : obfuscate_With_RSAPublic_Hexa - START
      - STEP 1 : Encrypt with 'RSA/ECB/PKCS1Padding' asymmetric algo (publicKey)
      - STEP 1 : Done => 'c9™®?y²;Ž´ØüOE¬!䮵á¹Ñ¨ö¼nÃó"'”S¤CWÑü ÚšÊ4Àø:S¸«îTZå~³z11ð2!Ù›¾ý9·ÌÁ *JÊbkN¦[î@ƒÙ¶Ù€ë°H3Ç“ öAÎKõ–kT¤6ŠæÏÿ'¦l¡‹gIn:GZ'
      - STEP 2 : Convert to hexa representation
      - STEP 2 : Done => '63399913AE8F79B23B8EB4D8FC4F45AC0621E4AE0613B5E1B9D1A8F604BC6EC3F322279453A44357D1FC0CDA9A02CA34C0F83A53B8ABEE545AE57EB37A3131F03221D99BBE04FD39B7CCC10C2A4AC38A626B4EA61E5BEE401683D9B6D980EBB04833C79320F641CE4BF5966B54A436040D8AE6CFFF27A66CA18B67496E3A475A'
      - RESULT = 'Hello beautiful pink unicorn !!!' obfuscated to '63399913AE8F79B23B8EB4D8FC4F45AC0621E4AE0613B5E1B9D1A8F604BC6EC3F322279453A44357D1FC0CDA9A02CA34C0F83A53B8ABEE545AE57EB37A3131F03221D99BBE04FD39B7CCC10C2A4AC38A626B4EA61E5BEE401683D9B6D980EBB04833C79320F641CE4BF5966B54A436040D8AE6CFFF27A66CA18B67496E3A475A'
      ----- FUNCTION : obfuscate_With_RSAPublic_Hexa - END

      ----- FUNCTION : obfuscate_With_RSAPublic_Hexa - START
      - STEP 1 : Encrypt with 'RSA/ECB/PKCS1Padding' asymmetric algo (publicKey)
      - STEP 1 : Done => '&„‰fæËÀÆ[ÀZRï$ÓÁçµæ2»áf©>Á0ì8¯i ½žóã W h?ÁíI*„ˆŽI²÷ëï8¦6Û H>êèÍ#v?å jú$´P!´Ï4`j€,â¤Ô#H8Œº¬}E’"·ò 4¨·b”ÉÂA?ÐúaGq:lô'
      - STEP 2 : Convert to hexa representation
      - STEP 2 : Done => '2684890366E6CBC0C65BC05A52EF24D3C1E7B5E632BBE10566A93EC130EC38AF1469A0BD9EF3E30957A06890C1ED492A84888E49B2F7EBEF38A636DBA0483EEAE8CD2306763F00E5096AFA24B45021B4CF340560076A802CE2A4D4182348388CBAAC7D45922214B7F20C34A8B7620A94C90213C2411D81D0FA6147713A6CF41E'
      - RESULT = 'Hello beautiful pink unicorn !!!' obfuscated to '2684890366E6CBC0C65BC05A52EF24D3C1E7B5E632BBE10566A93EC130EC38AF1469A0BD9EF3E30957A06890C1ED492A84888E49B2F7EBEF38A636DBA0483EEAE8CD2306763F00E5096AFA24B45021B4CF340560076A802CE2A4D4182348388CBAAC7D45922214B7F20C34A8B7620A94C90213C2411D81D0FA6147713A6CF41E'
      ----- FUNCTION : obfuscate_With_RSAPublic_Hexa - END

      ----- FUNCTION : illuminate_With_Hexa_RSAPrivate - START
      - STEP 1 : Convert from hexa representation
      - STEP 1 : Done => 'c9™®?y²;Ž´ØüOE¬!䮵á¹Ñ¨ö¼nÃó"'”S¤CWÑü ÚšÊ4Àø:S¸«îTZå~³z11ð2!Ù›¾ý9·ÌÁ *JÊbkN¦[î@ƒÙ¶Ù€ë°H3Ç“ öAÎKõ–kT¤6ŠæÏÿ'¦l¡‹gIn:GZ'
      - STEP 2 : Encrypt with 'RSA/ECB/PKCS1Padding' asymmetric algo (privateKey)
      - STEP 2 : Done => 'Hello beautiful pink unicorn !!!'
      ----- FUNCTION : illuminate_With_Hexa_RSAPrivate - END

      ----- FUNCTION : illuminate_With_Hexa_RSAPrivate - START
      - STEP 1 : Convert from hexa representation
      - STEP 1 : Done => '&„‰fæËÀÆ[ÀZRï$ÓÁçµæ2»áf©>Á0ì8¯i ½žóã W h?ÁíI*„ˆŽI²÷ëï8¦6Û H>êèÍ#v?å jú$´P!´Ï4`j€,â¤Ô#H8Œº¬}E’"·ò 4¨·b”ÉÂA?ÐúaGq:lô'
      - STEP 2 : Encrypt with 'RSA/ECB/PKCS1Padding' asymmetric algo (privateKey)
      - STEP 2 : Done => 'Hello beautiful pink unicorn !!!'
      ----- FUNCTION : illuminate_With_Hexa_RSAPrivate - END

       

    • test_03_obfuscateString_With_RSAPublic_SHA1_BASE64(String readableMessage) :
      …Java code:

      System.out.println("----------------- test_03_obfuscateString_With_RSAPublic_SHA1_BASE64(...)");
      final String obfuscatedValue = cryptoTools.obfuscate_With_RSAPublic_SHA1_BASE64(publicKey, readableMessage);
      Assert.assertNotNull(obfuscatedValue);
      Assert.assertNotEquals("Obfuscation result should be different than original string", readableMessage, obfuscatedValue);
      
      // Don't return the same obfuscated result for the same source
      final String newObfuscatedValue = cryptoTools.obfuscate_With_RSAPublic_SHA1_BASE64(publicKey, readableMessage);
      Assert.assertNotEquals("Obfuscation of a same value shouldn't return the same result", obfuscatedValue, newObfuscatedValue);
      

      …outputs:
      ----------------- test_03_obfuscateString_With_RSAPublic_SHA1_BASE64(...)
      ----- FUNCTION : obfuscate_With_RSAPublic_SHA1_BASE64 - START
      - STEP 1 : Encrypt with 'RSA/ECB/PKCS1Padding' asymmetric algo (publicKey)
      - STEP 1 : Done => 'f!¡ä¦ptÀØ&ï±qŽ âàyð׸^…Ÿ‰Ï.Ó&Lãêb§Jek-Œµ×@êLÇÅmϼávî[Añœa~òq;ug:‚ÏÆÏÞ‹º¨!&ÝgoC»cȇFírõLC„?£Ôñ%3{©.ó™€!È$²'
      - STEP 2 : Generate the obfuscated value with a hash 'SHA-1'
      - STEP 2 : Done => 'Câ0¬²äô©3–ŠÀ“Dˆzö'
      - STEP 3 : Transform to BASE64 from the value 'Câ0¬²äô©3–ŠÀ“Dˆzö'
      Before base64url : G0PiMKyy5PSpMx+WisCTRIh69hE=
      After base64url : G0PiMKyy5PSpMx-WisCTRIh69hE
      - STEP 3 : Done => 'G0PiMKyy5PSpMx-WisCTRIh69hE'
      - RESULT = 'Hello beautiful pink unicorn !!!' obfuscated to 'G0PiMKyy5PSpMx-WisCTRIh69hE'
      ----- FUNCTION : obfuscate_With_RSAPublic_SHA1_BASE64 - END

      ----- FUNCTION : obfuscate_With_RSAPublic_SHA1_BASE64 - START
      - STEP 1 : Encrypt with 'RSA/ECB/PKCS1Padding' asymmetric algo (publicKey)
      - STEP 1 : Done => 'Z&T;#k–YjÓ?ÖŸÆâvÒÂÒ÷o6Ã}²ü…Èœ5)‰ã~?ÿí?Š,mÇéºçó94EŸ³¼cÞ8z >?„\ ñŸÁ¸3WYoj)·ïª¬c‚$@ð9œ[?€l!&Æ[iÇZµb/—ÚL0ïÕÌÒ&ÐoY‚Ï2!3¢½ë'
      - STEP 2 : Generate the obfuscated value with a hash 'SHA-1'
      - STEP 2 : Done => 'ÇŒ Ü:V\_°0ÃÏÝm–Ç˱ '
      - STEP 3 : Transform to BASE64 from the value 'ÇŒ Ü:V\_°0ÃÏÝm–Ç˱ '
      Before base64url : x4wJ3DpWXF+wMMPP3W2WxxrLsQs=
      After base64url : x4wJ3DpWXF-wMMPP3W2WxxrLsQs
      - STEP 3 : Done => 'x4wJ3DpWXF-wMMPP3W2WxxrLsQs'
      - RESULT = 'Hello beautiful pink unicorn !!!' obfuscated to 'x4wJ3DpWXF-wMMPP3W2WxxrLsQs'
      ----- FUNCTION : obfuscate_With_RSAPublic_SHA1_BASE64 - END

       

    • test_04_obfuscateStringOfXxxxXChars_With_RSAPublic_SHA1_BASE64(int nbChars) :
      …Java code:

      // RSA Original Max length to obfuscate
      // 1024 bits = RSA keys length
      int RSA_ORIGINAL_MAX_LENGTH_TO_OBFUSCATE = 117; //1024/8 - 11;
      
      System.out.println("----------------- test_04_obfuscateStringOfXxxxXChars_With_RSAPublic_SHA1_BASE64("+nbChars+")");
      final StringBuilder sb = new StringBuilder();
      for (int i = 0; i < nbChars; i++) {
              sb.append("#");
      }
      final String obfuscatedValue = cryptoTools.obfuscate_With_RSAPublic_SHA1_BASE64(publicKey, sb.toString());
      Assert.assertNotNull(obfuscatedValue);
      Assert.assertTrue("Obfuscation result should have max " + RSA_ORIGINAL_MAX_LENGTH_TO_OBFUSCATE + " chars", obfuscatedValue.length() < RSA_ORIGINAL_MAX_LENGTH_TO_OBFUSCATE);
      

      …outputs:
      ----------------- test_04_obfuscateStringOfXxxxXChars_With_RSAPublic_SHA1_BASE64(118)
      ----- FUNCTION : obfuscate_With_RSAPublic_SHA1_BASE64 - START
      - STEP 1 : Encrypt with 'RSA/ECB/PKCS1Padding' asymmetric algo (publicKey)
      obfuscateStringOfXxxxXChars(118) -> IllegalBlockSizeException : OK

      ----------------- test_04_obfuscateStringOfXxxxXChars_With_RSAPublic_SHA1_BASE64(117)
      ----- FUNCTION : obfuscate_With_RSAPublic_SHA1_BASE64 - START
      - STEP 1 : Encrypt with 'RSA/ECB/PKCS1Padding' asymmetric algo (publicKey)
      - STEP 1 : Done => '\qçÜG•:ó¿ î•,!1$”ü/)< 'MS?Š]-ÙM_uŠ<ý΢Ë3' - STEP 3 : Transform to BASE64 from the value 'MS?Š]-ÙM_uŠ<ý΢Ë3' Before base64url : TR9TgYoAXS3ZTV91ihQ8/c6iyzM= After base64url : TR9TgYoAXS3ZTV91ihQ8_c6iyzM - STEP 3 : Done => 'TR9TgYoAXS3ZTV91ihQ8_c6iyzM'
      - RESULT = '#####################################################################################################################' obfuscated to 'TR9TgYoAXS3ZTV91ihQ8_c6iyzM'
      ----- FUNCTION : obfuscate_With_RSAPublic_SHA1_BASE64 - END

       

    • test_05_cipherAndDecipherContent_With_AesCbc() :
      …Java code:

      System.out.println("----------------- test_05_cipherAndDecipherContent_With_AesCbc(...)");
      String TEST_FILE = System.getProperty("user.dir") + "/resources/default-file.csv";
      final byte[] originalContent = readFully(new File(TEST_FILE));
      final byte[] cipheredContent = cryptoTools.encrypt_With_AesCbcSecret(secretKey, getResourceStream(TEST_FILE));
      Assert.assertFalse(Arrays.equals(originalContent, cipheredContent));
      final byte[] decipheredContent = cryptoTools.decryptStream_With_AesCbcSecret(secretKey, new ByteArrayInputStream(cipheredContent));
      Assert.assertArrayEquals(originalContent, decipheredContent);
      

      …outputs:
      ----------------- test_05_cipherAndDecipherContent_With_AesCbc(...)
      ----- FUNCTION : encrypt_With_AesCbcSecret - START
      - STEP 1 : Create a random initialization vector with a length 16 and write it in the outputstream
      - STEP 1 : Done => 'çŸor2\ÇÏÄ{®á'
      - STEP 2 : Encrypt with 'AES/CBC/PKCS5Padding' symmetric algo (secretKey)
      - STEP 2 : Done
      ----- FUNCTION : encrypt_With_AesCbcSecret - END

      ----- FUNCTION : decryptStream_With_AesCbcSecret - START
      - STEP 1 : Read the initialization vector with a length 16
      - STEP 1 : Done => 'çŸor2\ÇÏÄ{®á'
      - STEP 2 : Decrypt with 'AES/CBC/PKCS5Padding' symmetric algo (secretKey)
      - STEP 2 : Done
      ----- FUNCTION : decryptStream_With_AesCbcSecret - END

       

    • test_06_cipherAndDecipherFile_With_AesCbc() :
      …Java code:

      System.out.println("----------------- test_06_cipherAndDecipherFile_With_AesCbc(...)");
      final File cipheredFile = getTempFile();
      final File decipheredFile = getTempFile();
      String TEST_FILE = System.getProperty("user.dir") + "/resources/default-file.csv";
      
      try {
              final File readableFile = new File(TEST_FILE);
              cryptoTools.encrypt_With_AesCbcSecret(secretKey, readableFile, cipheredFile);
              Assert.assertFalse("Ciphered file must not be the same as the readable file", equals(readableFile, cipheredFile));
      
              cryptoTools.decryptFile_With_AesCbcSecret(secretKey, cipheredFile, decipheredFile);
              Assert.assertTrue("Deciphered file must be the same as the readable file", equals(readableFile, decipheredFile));
      } finally {
              remove(cipheredFile);
              remove(decipheredFile);
      }
      

      …outputs:
      ----------------- test_06_cipherAndDecipherFile_With_AesCbc(...)
      ----- FUNCTION : encrypt_With_AesCbcSecret - START
      - STEP 1 : Create a random initialization vector with a length 16 and write it in the outputstream
      - STEP 1 : Done => '©Lóò?0|z§6?Ô¦'
      - STEP 2 : Encrypt with 'AES/CBC/PKCS5Padding' symmetric algo (secretKey)
      - STEP 2 : Done
      ----- FUNCTION : encrypt_With_AesCbcSecret - END

      ----- FUNCTION : decryptStream_With_AesCbcSecret - START
      - STEP 1 : Read the initialization vector with a length 16
      - STEP 1 : Done => '©Lóò?0|z§6?Ô¦'
      - STEP 2 : Decrypt with 'AES/CBC/PKCS5Padding' symmetric algo (secretKey)
      - STEP 2 : Done
      ----- FUNCTION : decryptStream_With_AesCbcSecret - END

       

     

  4.  


     

  5. Concrete Example : Put into practice of previous classes

    Scenario:
    We need to send data of agencies (CustomerID) to remote organization with the following constraints:

    • Constraint n°1 : The data (source value) must be encrypted/obfuscated before sending to remote organization.
    • Constraint n°2 : The remote organization must not retrieve the source value from the obfuscated value (without reversibility).
    • Constraint n°3 : The source value mustn’t be stored clearly in any support.
    • Constraint n°4 : The source value must be obfuscated with asymmetric algorithm (use of public key).
    • Constraint n°5 : The public key can be changed because it is provided by the agencies.
    • Constraint n°6 : The private key is not owned by the solution/system.
    • Constraint n°7 : The solution must allow the changement of encryption’s public key without modify the obfuscated value sent to remote organization.
    • Constraint n°8 : An obfuscated value for a same source value mustn’t be changed even if the encryption’s key is modified.
    • Constraint n°9 : In problem case, the remote organization returns the obfuscated value to the solution in order to found the source value.

     
     
    Solution:
    First, we will use a TRANSCOding file containing the following columns:

    • “localValue” : source value encrypted with SECRET key of symmetric algorithm (ex: AES 128 bits) and encodage in HEXA => DATA_AES_HEXA
    • “obfuscatedValue” : source value encrypted with PUBLIC key of asymmetric algorithm (ex: RSA 1024 bits) and encodage in BASE64 => DATA_RSA_SHA1_BASE64

     

     
    Explanations:
    The “obfuscatedValue” column stores the obfuscated value sent to the remote organization.
    The “localValue” column stores the encrypted value (via SECRET Key) of source value in order to not store clearly it. This column allows to have a local value of “obfuscatedValue” in case of encryption key change (PUBLIC key).

     
    Example of sequencing:
    —- Time : t – with KEY_PUBLIC_1 and KEY_SECRET_LOCAL
    => CustomerID1 and CustomerID2 must be sent to remote organization (encryption with KEY_PUBLIC_1).
    TRANSCO file contents:
    CustomerID1 : "localValue1_keySECRET","obfuscatedValue1_keyPUBLIC1"
    CustomerID2 : "localValue2_keySECRET","obfuscatedValue2_keyPUBLIC1"

    —- Time : t+1 – with new KEY_PUBLIC_2 and KEY_SECRET_LOCAL
    => Modification of encryption’s key => KEY_PUBLIC_2
    => CustomerID3 must be sent to remote organization (encryption with new KEY_PUBLIC_2).
    TRANSCO file contents:
    CustomerID1 : "localValue1_keySECRET","obfuscatedValue1_keyPUBLIC1"
    CustomerID2 : "localValue2_keySECRET","obfuscatedValue2_keyPUBLIC1"
    CustomerID3 : "localValue3_keySECRET","obfuscatedValue2_keyPUBLIC2"

    —- Time : t+2 – with KEY_PUBLIC_2 and KEY_SECRET_LOCAL
    => CustomerID1 must be send again to remote organization with the new KEY_PUBLIC_2.
    => So, the SECRET key is used to generate the “localValue1_keySECRET” which is found in TRANSCO file.
    => This “localValue1_keySECRET” allows to retrieve and to send again the same “obfuscatedValue1_keyPUBLIC1” to remote organization.
    TRANSCO file contents NOT CHANGED:
    CustomerID1 : "localValue1_keySECRET","obfuscatedValue1_keyPUBLIC1"
    CustomerID2 : "localValue2_keySECRET","obfuscatedValue2_keyPUBLIC1"
    CustomerID3 : "localValue3_keySECRET","obfuscatedValue2_keyPUBLIC2"

    […]

    —- Time : t+n – with KEY_PUBLIC_2 and KEY_SECRET_LOCAL
    => Problem ocurs, so, the remote organization returns the “obfuscatedValue2_keyPUBLIC1” (corresponding to the CustomerID2):
    1. Retrieve the “localValue” in the TRANSCO file => “localValue2_keySECRET”
    2. Decrypt the “localValue2_keySECRET” with SECRET key in order to recover the CustomerID => CustomerID2

     

    Secondly, each DATA in TRANSCO file will encrypted in following manners:

    • For the “localValue”:
      1. CustomerID => encryption with symmetric LOCAL AES SECRET key -> DATA ENCRYPTED in large length => DATA_AES (reversibility possible only with SECRET key)
      2. DATA_AES => Encodage in HEXA to obtain DATA in normal characters => DATA_AES_HEXA
    • For the “obfuscatedValue”:
      1. CustomerID => encryption with asymmetric RSA PUBLIC key => DATA ENCRYPTED in large length => DATA_RSA (reversibility possible only with PRIVATE key)
      2. DATA_RSA => Hashing in SHA-1 => DATA HASHED (reversibility impossible) on max 27 bytes => DATA_RSA_SHA1 (reversibility impossible)
      3. DATA_RSA_SHA1 => Encodage in BASE64 to obtain DATA in normal characters => DATA_RSA_SHA1_BASE64

    Notes :

    • The TRANSCO file could be encrypted by AES/CBC algorithm.
    • The “obfuscatedValue” could be encrypted in following manner in order to allow the reversibility:
      1. CustomerID => encryption with asymmetric RSA PUBLIC key -> DATA ENCRYPTED in large length => DATA_RSA (reversibility possible only with PRIVATE key)
      2. DATA_RSA => Encodage in HEXA to obtain DATA in normal characters => DATA_RSA_HEXA

     

Resources:
https://www.flexiprovider.de/examples/ExampleRSA.html

Sources : example.zip

That’s all!!!

Huseyin OZVEREN