title: Decrypt Android SSE using OpenSSL
body: <p>The <a href="http://www.paranoiaworks.mobi/download/downloads.html" rel="noreferrer">Android SSE program</a> is great open source program for cross-platform encryption and decryption. They provide a client for other systems (based on their use of the Java-based bouncy castle library), but I am wondering if I can decrypt using openssl. This is mainly an exercise for me, but it would be nice to allow others to decrypt my files by sending them the openssl command to run. </p>
  
  <p>SSE is open source, but here's the core code for generating encryption keys: </p>
  
  <pre><code>/** Generate password-base Keys (128, 256, 448 bits) */
  private void generatePBKeys448Max(String pw, boolean unicodeAllowed) throws NoSuchAlgorithmException, InvalidKeySpecException 
  {
      pw = pw.trim();
      if(unicodeAllowed) pw = convertToCodePoints(pw);
  
      byte[] shaL1 = getSHA512Hash(pw.getBytes());    
      byte[] shaSalt = getSHA256Hash(Helpers.getSubarray(shaL1, 0, 8));
      byte[] shaIV = getSHA256Hash(Helpers.getSubarray(shaL1, 8, 8));
  
      PKCS12ParametersGenerator pGen = new PKCS12ParametersGenerator(new SHA1Digest());
      char[] passwordChars = pw.toCharArray();
      final byte[] pkcs12PasswordBytes = PBEParametersGenerator.PKCS12PasswordToBytes(passwordChars);
      pGen.init(pkcs12PasswordBytes, shaSalt, 600);
      CBCBlockCipher aesCBC = new CBCBlockCipher(new AESFastEngine());
      ParametersWithIV aesCBCParams = (ParametersWithIV) pGen.generateDerivedParameters(256, 128);
      aesCBC.init(false, aesCBCParams);       
      byte[] key = ((KeyParameter)aesCBCParams.getParameters()).getKey();
  
      byte[] k01 = Helpers.getSubarray(key, 0, 16);
      byte[] k02 = Helpers.getSubarray(key, 16, 16);
      keysVault.put("KS256", key);
      keysVault.put("KS128", Helpers.xorit(k01, k02));
  
      byte[] k31 = Helpers.getSubarray(shaL1, 40, 24);
      byte[] k32 = Helpers.concat(key, k31);
      keysVault.put("KS448", k32);
  
      String forIV = new String(getMD5Hash(shaIV));   
      PKCS12ParametersGenerator pGenIV = new PKCS12ParametersGenerator(new SHA1Digest());
      char[] ivChars = forIV.toCharArray();
      final byte[] pkcs12IVBytes = PBEParametersGenerator.PKCS12PasswordToBytes(ivChars);
      pGenIV.init(pkcs12IVBytes, getMD5Hash(shaSalt).getBytes(), 100);
      CBCBlockCipher aesCBC2 = new CBCBlockCipher(new AESFastEngine());
      ParametersWithIV aesCBCParams2 = (ParametersWithIV) pGenIV.generateDerivedParameters(256, 128);
      aesCBC2.init(false, aesCBCParams2);     
      byte[] keyIV = ((KeyParameter)aesCBCParams2.getParameters()).getKey();      
  
      byte[] k11 = Helpers.getSubarray(keyIV, 0, 16);
      byte[] k12 = Helpers.getSubarray(keyIV, 16, 16);
      byte[] ivTemp = Helpers.xorit(k11, k12);
      byte[] k21 = Helpers.getSubarray(ivTemp, 0, 8);
      byte[] k22 = Helpers.getSubarray(ivTemp, 8, 8);
      keysVault.put("IS128", ivTemp);
      keysVault.put("IS64", Helpers.xorit(k21, k22));
   }
  </code></pre>
  
  <p>So far I've done this (note the SSE is set to encrypt using AES 256) </p>
  
  <pre><code>$ echo "testpass" | openssl sha512 -out shaL1
  $ dd count=8 bs=1 if=shaL1 of=shaSalt
  $ dd skip=8 count=8 bs=1 if=shaL1 of=shaIV
  $ hexdump -ve '1/1 "%.2x"' shaSalt &gt; shaSalt.hex
  $ hexdump -ve '1/1 "%.2x"' shaIV &gt; shaIV.hex
  $ openssl aes-256-cbc -d -S shaSalt.hex -kfile shaIV.hex -p -in temp.enc -out mydir
  bad magic number
  </code></pre>
  
  <p>I'm very much a beginner here, so I may be missing quite a lot... :-/</p>