在上一篇文章实现了android通过证书文件进行安全传输的基础上,这篇文章讲解实现在android中通过非对称加密算法进行文件保存。
如何生成证书请参见“自定义证书android实现HTTPS通信”文章所述。在android中,通过KeyStore加载证书文件,并获取相应的PublicKey,通过Cipher设置对应的数据填充方式,此处要注意,填充的方式要与解密的方式相对应,否则会爆出异常。
主要实现代码如下:
@Override protectedvoidonCreate(BundlesavedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ButtonbtnSearch=(Button)findViewById(R.id.button1); btnSearch.setOnClickListener(this); } @Override publicbooleanonCreateOptionsMenu(Menumenu){ getMenuInflater().inflate(R.menu.main,menu); returntrue; } @Override publicvoidonClick(Viewv){ //TODOAuto-generatedmethodstub try{ PublicKeypublicKey=loadRSAPublicKey(); StringstrText=这里是机密信息!!!; byte[]bsText=strText.getBytes(UTF-8); byte[]bsEncode=encryptData(bsText,publicKey); saveFile(bsEncode); }catch(NoSuchAlgorithmExceptione){ //TODOAuto-generatedcatchblock e.printStackTrace(); }catch(CertificateExceptione){ //TODOAuto-generatedcatchblock e.printStackTrace(); }catch(NotFoundExceptione){ //TODOAuto-generatedcatchblock e.printStackTrace(); }catch(KeyStoreExceptione){ //TODOAuto-generatedcatchblock e.printStackTrace(); }catch(IOExceptione){ //TODOAuto-generatedcatchblock e.printStackTrace(); } } privatevoidsaveFile(byte[]bsData)throwsIOException{ Filefile=newFile(Environment.getExternalStorageDirectory(),encryptData.dat); FileOutputStreamfileOutputStream=newFileOutputStream(file); fileOutputStream.write(bsData); fileOutputStream.close(); } private PublicKey loadRSAPublicKey() throws NoSuchAlgorithmException, CertificateException,NotFoundException,IOException,KeyStoreException{ KeyStorets=null; ts=KeyStore.getInstance(BKS); ts.load(getResources().openRawResource(R.raw.mycert),123456.toCharArray()); EnumerationStringenumAliases=ts.aliases(); StringstrAliases=enumAliases.nextElement(); PublicKeypublicKey=ts.getCertificate(strAliases).getPublicKey(); returnpublicKey; } /* *数据加密 */ publicstaticbyte[]encryptData(byte[]data,PublicKeypublicKey) { try { Ciphercipher=Cipher.getInstance(RSA/ECB/PKCS1Padding); cipher.init(Cipher.ENCRYPT_MODE,publicKey); returncipher.doFinal(data); }catch(Exceptione) { e.printStackTrace(); returnnull; } } 生成完成加密文件后,我们通过adb将加密的文件导入到电脑中。 adb pull /sdcard/encryptData.dat c:\encryptData.dat
在pc端,通过一个c#程序进行解密,并显示出被加密的数据,通过X509Certificate2加载pfx证书文件,并获得私钥对象RSACryptoServiceProvider,将私钥对象赋予RSACryptoServiceProvider对象后通过调用Decrypt获得解密后的byte数组。最后需要对byte数组进行utf-8编码成字符串后进行显示。主要代码如下:
static { voidMain(string[]args) stringstrCertFileFullName=@D:\cert\myCert.pfx; stringstrFileName=@c:\encryptData.dat; FileStreamfs=newFileStream(strFileName,FileMode.Open,FileAccess.Read); byte[]encryptedData=newbyte[fs.Length]; fs.Read(encryptedData,0,encryptedData.Length); fs.Close(); X509Certificate2 prvcrt = new X509Certificate2(strCertFileFullName, , X509KeyStorageFlags.Exportable); RSACryptoServiceProviderprvkey=(RSACryptoServiceProvider)prvcrt.PrivateKey; byte[]decryptedData=RSADecrypt(encryptedData,prvkey.ExportParameters(true), false); prvkey.Clear(); Console.WriteLine(解密出的信息:\n{0},Encoding.UTF8.GetString(decryptedData)); } staticpublicbyte[]RSADecrypt(byte[]DataToDecrypt,RSAParametersRSAKeyInfo,bool DoOAEPPadding) { try { byte[]decryptedData; using(RSACryptoServiceProviderRSA=newRSACryptoServiceProvider()) { RSA.ImportParameters(RSAKeyInfo); decryptedData=RSA.Decrypt(DataToDecrypt,false); } returndecryptedData; } catch(CryptographicExceptione) { Console.WriteLine(e.ToString()); returnnull; } }
执行结果如图1所示。
图1
(完)