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