使用AES端到端加密短信

时间:2018-12-22 05:47:08

标签: android encryption aes

Android中的端到端加密。我正在尝试在android中实现聊天应用程序。

我已经尝试使用AES算法进行加密和解密,从而成功生成了私钥和公钥

GenerateRsaKeyPair.java类,用于生成公钥和私钥   尝试{

        // 1. generate public key and private key


            KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
            keyPairGenerator.initialize(1024); // key length
            KeyPair keyPair = keyPairGenerator.genKeyPair();
            String privateKeyString = Base64.encodeToString(keyPair.getPrivate().getEncoded(), Base64.DEFAULT);
            publicKeyString = Base64.encodeToString(keyPair.getPublic().getEncoded(), Base64.DEFAULT);

            // 2. print both keys
            System.out.println("rsa key pair generated\n");
            Log.e("privateKey",  privateKeyString );
            Log.e("publicKey",  publicKeyString );
            isgenerated=false;




    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    }

此代码对邮件进行加密  尝试{

               // 1. generate secret key using AES
               KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
               keyGenerator.init(128); // AES is currently available in three key sizes: 128, 192 and 256 bits.T
               // the design and strength of all key lengths of the AES algorithm are sufficient to protect classified information up to the SECRET level
               SecretKey secretKey = keyGenerator.generateKey();
               plainText=editTextsend.getText().toString();

               // 2. get string which needs to be encrypted // our case message
               String text = plainText;//"<your_string_which_needs_to_be_encrypted_here>"
               Log.e("string",text);

               // 3. encrypt string using secret key
               byte[] raw = secretKey.getEncoded();
               SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
               Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");//PKCS5Padding
               cipher.init(Cipher.ENCRYPT_MODE, skeySpec, new IvParameterSpec(new byte[16]));
               String cipherTextString = Base64.encodeToString(cipher.doFinal(text.getBytes(Charset.forName("UTF-8"))), Base64.DEFAULT);
               Log.e("ciphertext",cipherTextString);
               // 4. get public key
               X509EncodedKeySpec publicSpec = new X509EncodedKeySpec(Base64.decode(publicKeyString, Base64.DEFAULT));
               KeyFactory keyFactory = KeyFactory.getInstance("RSA");
               PublicKey publicKey = keyFactory.generatePublic(publicSpec);

               // 6. encrypt secret key using public key
               Cipher cipher2 = Cipher.getInstance("RSA/ECB/OAEPWithSHA1AndMGF1Padding");
               cipher2.init(Cipher.ENCRYPT_MODE, publicKey);
               String encryptedSecretKey = Base64.encodeToString(cipher2.doFinal(secretKey.getEncoded()), Base64.DEFAULT);
               Log.e("encryptedSecretKey",encryptedSecretKey);

               // 7. pass cipherTextString (encypted sensitive data) and encryptedSecretKey to your server via your preferred way.
               // Tips:
               // You may use JSON to combine both the strings under 1 object.
               // You may use a volley call to send this data to your server.

           } catch (NoSuchAlgorithmException | InvalidKeyException | NoSuchPaddingException | IllegalBlockSizeException | BadPaddingException | InvalidKeySpecException | InvalidAlgorithmParameterException e) {
               e.printStackTrace();
           }

此人成功解密了消息   尝试{

        // 1. Get private key
        PKCS8EncodedKeySpec privateSpec = new PKCS8EncodedKeySpec(Base64.decode(privateKey, Base64.DEFAULT));
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PrivateKey privateKey = keyFactory.generatePrivate(privateSpec);
        Log.e("secretKey",privateKey+"");
        // 2. Decrypt encrypted secret key using private key
        Cipher cipher1 = Cipher.getInstance("RSA/ECB/OAEPWithSHA1AndMGF1Padding");
        cipher1.init(Cipher.DECRYPT_MODE, privateKey);
        byte[] secretKeyBytes = cipher1.doFinal(Base64.decode(encryptedSecretKeyString, Base64.DEFAULT));
        SecretKey secretKey = new SecretKeySpec(secretKeyBytes, 0, secretKeyBytes.length, "AES");
        Log.e("secretKey",secretKey+"");
        // 3. Decrypt encrypted text using secret key
        byte[] raw = secretKey.getEncoded();
        SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        cipher.init(Cipher.DECRYPT_MODE, skeySpec, new IvParameterSpec(new byte[16]));
        byte[] original = cipher.doFinal(Base64.decode(encryptedTextString, Base64.DEFAULT));
        String text = new String(original, Charset.forName("UTF-8"));
        Log.e("text",text);
        // 4. Print the original text sent by client
        System.out.println("text\n" + text + "\n\n");


    } catch (NoSuchAlgorithmException | InvalidKeySpecException | InvalidKeyException | NoSuchPaddingException | IllegalBlockSizeException | BadPaddingException | InvalidAlgorithmParameterException e) {
        e.printStackTrace();
    }

我期望特定用户的私钥和公钥应该相同,但是在我构建应用程序的代码中,它每次都会生成不同的私钥和公钥,因此我如何以前管理当前用户聊天消息和数据,并且每次也可以进行一对一聊天和群聊。 任何答案和建议都是可以理解的。

1 个答案:

答案 0 :(得分:1)

将您的私钥存储在KeyStore中,最好是系统密钥存储区,以提供额外的保护。对于Android,例如,先阅读有关Android密钥存储系统的this official article(因为这也可能会影响密钥对的生成)。当然也可以将PKCS#8编码的二进制私钥存储在持久性存储(“磁盘”)中,但是不建议在没有保护的情况下存储密钥。存储在应用程序中的密码是绝对可以提供的最低安全性。通常你会尝试更高的目标。

您的公钥可以简单地使用getEncoded进行编码。然后,您可以将KeyFactory与算法"RSA"配合使用来检索公钥。该公钥通常被编码为X509SubjectPublicKeyInfo对象。 X.509当然是X.509 certificate 规范的提示:密钥被编码为兼容的二进制格式。只要可以受信任,公钥就不需要太多保护。攻击者当然不能用自己的公钥替换它们。

如何信任公共密钥是整本有关密钥管理的书籍的主题。对于非对称密钥,通常使用PKI(公共密钥基础结构)分发并验证包装在公共密钥证书中的密钥状态。如果为此使用X.509证书,则PKI通常称为PKIX;浏览器中的TLS证书是很大的PKIX系统的一部分。