将硬编码文件解密为byte []

时间:2012-08-21 10:50:16

标签: java android encryption

这实际上是两个人......

首先我需要

  1. 阅读文件的内容
  2. 将其加密为byte[]
  3. byte[]写入文件或其他任何内容......
  4. 然后#2或#3的结果将进入另一个项目。我正在努力保护我们的PEM / DER键。

    对于解密,我需要

    1. byte[]
    2. 的形式阅读加密文件的内容
    3. 将其解密为byte[]
    4. 将解密数据写入文件或使用它而不是文件
    5. 现在,我有一些基本的加密代码

              KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
          keyGenerator.init(128); // 192 and 256 bits may not be available
      
          SecretKey secretKey = keyGenerator.generateKey();
      
          Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
      
      
          // By initializing the cipher in CBC mode, an "initialization vector" has been randomly
          // generated. This initialization vector will be necessary to decrypt the encrypted data.
          // It is safe to store the initialization vector in plain text for later use. You can obtain
          // it's bytes by calling iv.getIV().
          cipher.init(Cipher.ENCRYPT_MODE, secretKey);
          IvParameterSpec iv = cipher.getParameters().getParameterSpec(IvParameterSpec.class);
              //      IvParameterSpec iv = new IvParameterSpec(IV); //used for the hardcoded one
      
              byte[] encryptedData = cipher.doFinal(data);
      

      并解密一个

          cipher.init(Cipher.DECRYPT_MODE, secretKey, iv);
          byte[] decryptedData = cipher.doFinal(encryptedData);
          System.out.println("decrypted: " + new String(decryptedData));
      

      问题是:

      鉴于一个用例场景,人们很少加密某些内容并分发将在运行时解密的加密密钥,除了密文之外还需要保存什么?

      我知道我需要保存IV,但是当我解密时效果不是很好 - 这让我相信我也需要保存secretKey。

      有人能给我任何提示,指针或一般安全提示以获得更好的解决方案吗?如果我需要保存密钥,IV和加密数据,我应该在哪里存储它们?也许硬编码密钥并将IV存储在加密数据中?也许硬编码IV和密钥只是将加密数据存储在文件中?

      这不是关于理论安全性,将此视为您可能对试图窃取您的钥匙的人造成的最大的麻烦和不便。我们都知道我无法完全隐藏它们。

      我非常需要这个人开始使用Decrypting an encrypted file and executing in Java

      但是,如果有更好的方法将安全数据提供给PemKeyReader,我全都耳朵。

2 个答案:

答案 0 :(得分:1)

共享密钥和加密某些东西是两件完全不同的事情。 How to share keys

话虽如此,AES 128位是比3DES强大的加密算法所以您可以做的是保持PKI基础设施到位以交换AES keys然后加密并解密使用它们。

为什么不RSARSA需要最小512位才能将其视为最强,如果增加更多位,则会增加加密和解密所需的时间。

SO AES快速而安全。

使用SecretKeySpec从byte []

创建密钥
public static void main(String[] args) throws Exception
{
    // Initialise secret key with predefined byte array [] like below. I
    // have used simple string to array method to generate 16 byte array.
    // AES Key must be minimum 16 bytes.
    // Now you can put this byte array some where is .SO file.
    // Generate new Key using this byte []
    // Then you can generate a key using device specific information at
    // first boot up.
    // Use second key to encrypt data and first key to encrypt the second
    // key
    // I Hope it clears all the doubts
    SecretKey key = new SecretKeySpec("ABCDEFGHIJKLMNOP".getBytes(), "AES");
    System.out.println(Arrays.toString(key.getEncoded()));
    // Initialise Cipher with AES Algorithm
    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
    // Set The Encrypt Mode
    cipher.init(Cipher.ENCRYPT_MODE, key);
    // Encrypt some bytes
    byte[] encrypted = cipher.doFinal("ABCDEFGH".getBytes());
    // Print it to vefiry
    System.out.println(Arrays.toString(encrypted));

    // Get The IV
    byte[] iv = cipher.getIV();
    System.out.println(iv.length);
    // Now why storing you can create structure like [16 IV][Encrypted Data]
    // And while decrypting you can read first [16] bytes IV and then
    // decrypt remaining bytes

    //byte[] iv = new byte[16];
    // System.arraycopy(encrypted, 0, iv, 0, 16)
    //Copy remaining bytes to decrypt


    // set cipher to decrypt mode

    cipher.init(Cipher.DECRYPT_MODE, key,new IvParameterSpec(iv));

    // decrypt it
    byte[] decrypted = cipher.doFinal(encrypted);
    System.out.println(new String(decrypted));

}

现在编写一个算法,它将从一些随机数据中生成byte [],如设备名称,用户名,随机种子等。

您可以在C中编写该算法并创建.SO文件并使用byte []获取Native calls,从而为算法源代码添加更多保护。

做这一切有什么好处?

  1. 如果您的黑客入侵,则需要实时环境才能运行创建密钥。
  2. 即使有人破解了它,也会受到损害,即1台设备
  3. 黑客将不得不重复使用每个设备,这是非常不可能的。

答案 1 :(得分:1)

通过阅读Oracle Java教程的"Byte Streams""Buffered Streams"部分,可以最好地解决问题的I / O方面问题。您可以通过将字节写入ByteArrayOutputStream来累积内存中的字节,然后使用toByteArray()方法将字节作为byte[]来获取。