Эх сурвалжийг харах

append salt to private key

tobiasKaminsky 7 жил өмнө
parent
commit
917189f3ca

+ 15 - 1
src/androidTest/java/com/owncloud/android/util/EncryptionTestIT.java

@@ -234,7 +234,21 @@ public class EncryptionTestIT {
         Set<String> ivs = new HashSet<>();
 
         for (int i = 0; i < 50; i++) {
-            assertTrue(ivs.add(EncryptionUtils.encodeBytesToBase64String(EncryptionUtils.generateIV())));
+            assertTrue(ivs.add(EncryptionUtils.encodeBytesToBase64String(
+                    EncryptionUtils.randomBytes(EncryptionUtils.ivLength))));
+        }
+    }
+
+    /**
+     * generates new salt and tests if they are unique
+     */
+    @Test
+    public void testSalt() {
+        Set<String> ivs = new HashSet<>();
+
+        for (int i = 0; i < 50; i++) {
+            assertTrue(ivs.add(EncryptionUtils.encodeBytesToBase64String(
+                    EncryptionUtils.randomBytes(EncryptionUtils.saltLength))));
         }
     }
 

+ 1 - 1
src/main/java/com/owncloud/android/operations/UploadFileOperation.java

@@ -511,7 +511,7 @@ public class UploadFileOperation extends SyncOperation {
             }
 
             if (iv == null || iv.length == 0) {
-                iv = EncryptionUtils.generateIV();
+                iv = EncryptionUtils.randomBytes(EncryptionUtils.ivLength);
             }
 
             EncryptionUtils.EncryptedFile encryptedFile = EncryptionUtils.encryptFile(mFile, key, iv);

+ 23 - 18
src/main/java/com/owncloud/android/utils/EncryptionUtils.java

@@ -93,15 +93,16 @@ import javax.crypto.spec.SecretKeySpec;
 public class EncryptionUtils {
     private static String TAG = EncryptionUtils.class.getSimpleName();
 
-    private static byte[] salt = "$4$YmBjm3hk$Qb74D5IUYwghUmzsMqeNFx5z0/8$".getBytes();
+    public static String PUBLIC_KEY = "PUBLIC_KEY";
+    public static String PRIVATE_KEY = "PRIVATE_KEY";
+    public static int ivLength = 16;
+    public static int saltLength = 40;
+    
     private static String ivDelimiter = "fA=="; // "|" base64 encoded
     private static int iterationCount = 1024;
     private static int keyStrength = 256;
-
-    public static String PUBLIC_KEY = "PUBLIC_KEY";
-    public static String PRIVATE_KEY = "PRIVATE_KEY";
-    public static String AES_CIPHER = "AES/GCM/NoPadding";
-    public static String RSA_CIPHER = "RSA/ECB/OAEPWithSHA-256AndMGF1Padding";
+    private static String AES_CIPHER = "AES/GCM/NoPadding";
+    private static String RSA_CIPHER = "RSA/ECB/OAEPWithSHA-256AndMGF1Padding";
 
     /*
     JSON
@@ -267,7 +268,7 @@ public class EncryptionUtils {
     /**
      * @param ocFile             file do crypt
      * @param encryptionKeyBytes key, either from metadata or {@link EncryptionUtils#generateKey()}
-     * @param iv                 initialization vector, either from metadata or {@link EncryptionUtils#generateIV()}
+     * @param iv                 initialization vector, either from metadata or {@link EncryptionUtils#randomBytes(int)}
      * @return encryptedFile with encryptedBytes and authenticationTag
      */
     @RequiresApi(api = Build.VERSION_CODES.KITKAT)
@@ -283,7 +284,7 @@ public class EncryptionUtils {
     /**
      * @param file               file do crypt
      * @param encryptionKeyBytes key, either from metadata or {@link EncryptionUtils#generateKey()}
-     * @param iv                 initialization vector, either from metadata or {@link EncryptionUtils#generateIV()}
+     * @param iv                 initialization vector, either from metadata or {@link EncryptionUtils#randomBytes(int)}
      * @return encryptedFile with encryptedBytes and authenticationTag
      */
     @RequiresApi(api = Build.VERSION_CODES.KITKAT)
@@ -437,7 +438,7 @@ public class EncryptionUtils {
             CertificateException {
 
         Cipher cipher = Cipher.getInstance(AES_CIPHER);
-        byte[] iv = generateIV();
+        byte[] iv = randomBytes(ivLength);
 
         Key key = new SecretKeySpec(encryptionKeyBytes, "AES");
         GCMParameterSpec spec = new GCMParameterSpec(128, iv);
@@ -500,6 +501,7 @@ public class EncryptionUtils {
         Cipher cipher = Cipher.getInstance(AES_CIPHER);
 
         SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
+        byte[] salt = randomBytes(saltLength);
         KeySpec spec = new PBEKeySpec(keyPhrase.toCharArray(), salt, iterationCount, keyStrength);
         SecretKey tmp = factory.generateSecret(spec);
         SecretKeySpec key = new SecretKeySpec(tmp.getEncoded(), "AES");
@@ -510,9 +512,10 @@ public class EncryptionUtils {
 
         byte[] iv = cipher.getParameters().getParameterSpec(IvParameterSpec.class).getIV();
         String encodedIV = encodeBytesToBase64String(iv);
+        String encodedSalt = encodeBytesToBase64String(salt);
         String encodedEncryptedBytes = encodeBytesToBase64String(encrypted);
 
-        return encodedEncryptedBytes + ivDelimiter + encodedIV;
+        return encodedEncryptedBytes + ivDelimiter + encodedIV + ivDelimiter + encodedSalt;
     }
 
     /**
@@ -526,19 +529,21 @@ public class EncryptionUtils {
     public static String decryptPrivateKey(String privateKey, String keyPhrase) throws NoSuchPaddingException,
             NoSuchAlgorithmException, NoSuchProviderException, InvalidKeyException, BadPaddingException,
             IllegalBlockSizeException, InvalidKeySpecException, InvalidAlgorithmParameterException {
-        Cipher cipher = Cipher.getInstance(AES_CIPHER);
 
+        // split up iv, salt
+        String[] strings = privateKey.split(ivDelimiter);
+        String realPrivateKey = strings[0];
+        byte[] iv = decodeStringToBase64Bytes(strings[1]);
+        byte[] salt = decodeStringToBase64Bytes(strings[2]);
+
+        Cipher cipher = Cipher.getInstance(AES_CIPHER);
         SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
         KeySpec spec = new PBEKeySpec(keyPhrase.toCharArray(), salt, iterationCount, keyStrength);
         SecretKey tmp = factory.generateSecret(spec);
         SecretKeySpec key = new SecretKeySpec(tmp.getEncoded(), "AES");
 
-        // handle private key
-        String[] strings = privateKey.split(ivDelimiter);
-        String realPrivateKey = strings[0];
-        String iv = strings[1];
 
-        cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(decodeStringToBase64Bytes(iv)));
+        cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv));
 
         byte[] bytes = decodeStringToBase64Bytes(realPrivateKey);
         byte[] decrypted = cipher.doFinal(bytes);
@@ -625,9 +630,9 @@ public class EncryptionUtils {
         return null;
     }
 
-    public static byte[] generateIV() {
+    public static byte[] randomBytes(int size) {
         SecureRandom random = new SecureRandom();
-        final byte[] iv = new byte[16];
+        final byte[] iv = new byte[size];
         random.nextBytes(iv);
 
         return iv;