如何在Android中加密/解密发送/接收的消息?

时间:2014-12-20 06:29:49

标签: java android encryption rsa privacy

我们正在构建一个聊天客户端(类似于Whatsapp等),用于发送和接收私人消息。为了保护隐私,我们决定在到达和发送时加密和解密消息。

我认为我们可以使用RSA私钥和公钥进行加密。据我所知,我们通常需要两对密钥,其中一对位于服务器上,另一对位于电话上。这提出了一些我在这里问的问题。

  1. 如何在android中生成密钥对?
  2. 应该如何存储?
  3. 我是否需要为服务器上的每个用户以及客户端使用不同的密钥对?
  4. 请随意添加任何有用的信息,因为我是安全的新手。

3 个答案:

答案 0 :(得分:2)

您需要一个中央服务器,为每个用户提供证书以验证用户身份(否则您将始终容易受到中间人攻击)。因此,对于两个用户(Joe和Sally),将有三个证书:1)验证中央服务器的证书,2)验证Joe的证书和3)验证Sally的证书。

因此,当Joe想要与Sally建立联系时,应该发生以下情况:

  1. Joe从中央服务器请求Sally的公钥。
    1. Joe通过服务器的公钥验证服务器(通过检查数字证书)。
    2. Joe使用服务器的公钥加密共享密钥,然后将加密的共享密钥发送到服务器。
    3. 只有服务器可以解密Joe的共享密钥,因此使用此共享密钥加密(通过Symmetric Cryptography)Sally的公钥并发送Sally的公钥,通过Joe提出的共享密钥加密到Joe。
    4. Joe现在拥有Sally的公钥;经过身份验证,因为它来自经过身份验证的服务器。
    5. Joe向Sally发送请求以发起通信,将自己标识为" Joe"以及数字证书。
      1. 莎莉认证"乔"通过中央服务器。
      2. Sally检索Joe的公钥,就像Joe从中央服务器获取Sally的公钥一样。
      3. Sally向Joe发送共享密钥。
        1. Sally使用Joe的公钥来加密多部分消息,其中包括1)共享密钥和2)用Sally私钥加密的数字证书。
      4. Joe收到了Sally的加密邮件(只有Joe可以解密,因为它是用Joe的公钥加密的。)
        1. Joe解密邮件并收到Sally提议的共享密钥。
        2. Joe收到使用Joe公钥加密的Sally数字证书,并尝试使用之前从中央服务器获得的Sally公钥进行解密。
        3. 如果Joe成功解密数字证书,那么Joe可以放心,Sally是提出共享密钥的人。
        4. Joe使用共享密钥通过对称加密向Sally发送共享密钥的确认。
        5. Sally通过Sally建议的共享密钥接收Joe的确认。
        6. Sally和Joe现在可以通过Sally最初提出的共享密钥使用对称加密来回通信。
        7. 那为什么所有这一切都是必要的?首先,你需要一个"信任的"经纪人(那是中央服务器)。否则你永远无法确定与谁沟通。您可能会问:为什么只有Joe能够解密它(如果Sally使用Joe的公钥加密),Sally需要签署她的共享密钥?原因是任何人可以通过Joe的公钥加密共享密钥!因此,如果Joe接收到未签名的共享密钥,则他可以开始与中间的人通信,该中间人仅使用Joe的公钥生成共享密钥。正如Sally需要确认Joe是尝试与她沟通的实际实体一样,Joe需要确保他收到的共享密钥是实际上是来自Sally的(因此她需要与她的私人签约)键)。

          RSA 不安全 !!!如果有足够的流量,则 可以解密由RSA编码的消息。因此,您应该有一个协议来定期更新用于身份验证的公钥/私钥。这对用户来说很简单:您的中央服务器将为每个用户保留公钥。您的服务器应定期请求每个用户生成新的私钥/公钥对,并将公钥发送到要更新的服务器(此通信可以通过每个用户使用的先前私钥/公钥完成)。

          它多一点困难"对于中央服务器本身。如果您的中央服务器希望更改其私钥/公钥(验证服务器),则需要与每个用户通信以使每个用户都知道更改。当用户更改他/她的私钥/公钥时,它是一对一的通信(仅在用户和服务器之间)但是当服务器想要更改私钥/公钥,它必须与所有用户进行通信!

          <强>警告:

          我并不是说我上面提出的是&#34;规范&#34;图案。我声称,如果您遵循上述规定,您将确保真实性和完整性。即您可以保证与中央服务器认为是&#34; Joe&#34;和&#34;莎莉&#34; 你可以保证只有 Joe和Sally可以通信,因为包括中央服务器在内的任何人都不知道Joe和Sally用来通信的共享密钥(Joe除外)当然还有莎莉。

答案 1 :(得分:1)

有许多加密/解密算法,如数据加密标准(DES),Playfair等等。 你可以使用那些。如果你愿意,可以制作自己的算法。我曾经制作了一个信使应用程序,并且我制作了自己的加密/解密算法。

您也可以选择对称或非对称密钥算法...继续工作,信使有一个很好的范围.. :)

答案 2 :(得分:1)

最常用的加密/解密技术是AES。您可以找到更多信息访问http://en.wikipedia.org/wiki/Advanced_Encryption_Standard? 您只需要定义一个KEY(例如:25346483936),它在移动设备和服务器端都是通用的,以及加密所需的IV_Vector,从下面的代码中可以更清楚。 注意:密钥的长度必须等于IV_Vector数组大小,在下面的示例中它是16。现在使用加密方法,您可以在通过非安全网络将信息发送到服务器之前对其进行加密。同样,您可以使用DecryptData类解密从服务器接收的信息。

public class Constants {

// encryption/decryption
public static String AES_KEY = "0366D8637F9C6B21";      
public static byte[] IV_VECTOR = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};


}



/**
 * This class is used to decrypt an encrypted string value.
 * 
 * @author kthakur
 *
 */
public class EncryptDecrytData {


    /**
     * This method is used to encrypt a string value.
     * 
     * @param text
     *          - string value to be encrypted.
     *          
     * @return result(encrypted string) as String
     * 
     * @throws Exception
     * 
     */
    @TargetApi(8)
    public static String encrytData(String text) throws Exception {

        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
        byte[] static_key = Constants.AES_KEY.getBytes();

        SecretKeySpec keySpec = new SecretKeySpec(static_key, "AES");
        IvParameterSpec ivSpec = new IvParameterSpec(Constants.IV_VECTOR);
        cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);

        byte[] results = cipher.doFinal(text.getBytes());

        String result = Base64.encodeToString(results, Base64.NO_WRAP|Base64.DEFAULT);
        return result;

    }

    /**
     * This method is used to decrypt a string value.
     * 
     * @param text
     *          - string value to be decrypted.
     * @return result(decrypted string) as String
     * 
     * @throws Exception
     */
    @SuppressLint("NewApi")
    public static String decryptData(String text)throws Exception{

        byte[] encryted_bytes = Base64.decode(text, Base64.DEFAULT);

        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
        byte[] static_key = Constants.AES_KEY.getBytes();

        SecretKeySpec keySpec = new SecretKeySpec(static_key, "AES");
        IvParameterSpec ivSpec = new IvParameterSpec(Constants.IV_VECTOR);
        cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);

        byte[] decrypted = cipher.doFinal(encryted_bytes);
        String result = new String(decrypted);

        return result;
    }
}