編輯:關於Android編程
這個世界很精彩,這個世界很無奈。是的,在互聯網時代,如何保護自己的數據,如何對數據進行加密和效驗就變得非常的重要。這裡總結一下Android平台使用Java語言,利用RSA算法對數據進行校驗的經驗。
先來看下如何RSA加密算法對數據進行校驗的流程:
1、首先要用openssh之類的程序生成一個私鑰
2、再根據私鑰生成一個公鑰
3、使用私鑰和公鑰,對數據進行簽名,得到簽名文件。
4、使用公鑰和簽名文件就可以對數據進行校驗了。
再來看下如何實現:
1、生成2048位的私鑰:
openssl genrsa -out private.pem 2048
2、生成公鑰
使用openssh也可以生成公鑰,但是在使用的過程中,發現由於格式的問題,使用openssh生成的公鑰在Java中使用時總是提示異常,所以最後還是根據網上的相關資料,使用Java語言來寫了程序,使用的公鑰可以在Java中使用,代碼如下:
GenPublic.java
import java.io.BufferedReader; import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.FileReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.PrintStream; import java.math.BigInteger; import java.security.KeyFactory; import java.security.KeyPair; import java.security.PublicKey; import java.security.Security; import java.security.Signature; import java.security.interfaces.DSAParams; import java.security.interfaces.DSAPublicKey; import java.security.interfaces.RSAPublicKey; import java.security.spec.X509EncodedKeySpec; import java.security.spec.RSAPublicKeySpec; import javax.xml.bind.DatatypeConverter; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.openssl.PEMReader; import org.bouncycastle.util.encoders.Base64; public class GenPublic { public static PrintStream out = System.out; public static PrintStream err = System.err; private static void genPublicKey(String privateFile,String pubFile) { try { PEMReader pemReader = new PEMReader(new FileReader(privateFile)); KeyPair pair = (KeyPair)pemReader.readObject(); PublicKey pubKey = pair.getPublic(); FileOutputStream outPub = new FileOutputStream(pubFile); byte[] bytes = pair.getPublic().getEncoded(); outPub.write(bytes); outPub.close(); } catch (Exception e) { e.printStackTrace(); } } public static void main(String[] args) throws Exception { if (args.length != 2) { err.println(Usage: java GenPublic); System.exit(1); } File pemFile = new File(args[0]); if(!pemFile.exists()) { err.println(PEM File Does Not Exist); System.exit(1); } Security.addProvider(new BouncyCastleProvider()); genPublicKey(args[0],args[1]); } }
使用方法:
先編譯:
export CLASSPATH=.:bcprov-jdk15-140.jar javac GenPublic.java
再使用編譯的程序生成公鑰:
java GenPublic private.pem public.bin
用到的庫可以在本文最後的鏈接中下載。
再來看看生成簽名文件的Java代碼:
Sign.java
import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.io.PrintStream; import java.security.KeyFactory; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.PublicKey; import java.security.SecureRandom; import java.security.Security; import java.security.Signature; import java.security.spec.X509EncodedKeySpec; import javax.xml.bind.DatatypeConverter; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.jce.provider.JDKKeyPairGenerator; import org.bouncycastle.openssl.PEMReader; import org.bouncycastle.openssl.PEMWriter; class Sign { public static PrintStream out = System.out; public static PrintStream err = System.err; private static byte[] pubKeyData = null; public static void main(String[] args) throws Exception { if(args.length < 4) { err.println(Usage: java JavaSign); System.exit(1); } File pemFile = new File(args[0]); File pubFile = new File(args[1]); File dataFile = new File(args[2]); if(!dataFile.exists()) { err.println(Data File Does Not Exist); System.exit(1); } Security.addProvider(new BouncyCastleProvider()); KeyPair keys = null; if(!pemFile.exists()) { err.println(PEM File Does Not Exist. Generating.); KeyPairGenerator r = KeyPairGenerator.getInstance(RSA); //keysize in bits is 2048 r.initialize(2048,new SecureRandom()); keys = r.generateKeyPair(); PEMWriter pemWriter = new PEMWriter(new FileWriter(pemFile)); pemWriter.writeObject(keys); pemWriter.close(); //You must flush or close the file or else it will not save } else { keys = (KeyPair) new PEMReader(new FileReader(pemFile)).readObject(); } //read data file into signature instance FileInputStream fin = new FileInputStream(dataFile); byte[] data = new byte[(int) dataFile.length()]; fin.read(data); fin.close(); //Sign the data Signature sg = Signature.getInstance(SHA1withRSA); sg.initSign(keys.getPrivate()); sg.update(data); //output base64 encoded binary signature byte signBytes[] = sg.sign(); fin = new FileInputStream(pubFile); pubKeyData = new byte[(int) pubFile.length()]; fin.read(pubKeyData); fin.close(); int len = pubKeyData.length; for (int i=0;i
同樣先編譯:
export CLASSPATH=.:bcprov-jdk15-140.jar javac Sign.java
再看看看如何生成簽名文件:
java JavaSign private.pem public.bin test.dat sign.bin
這裡的test.dat即是要校驗的數據,sign.bin為生成的簽名文件:
最後,就是如何使用公鑰和簽名文件進行校驗數據了:
來看下面的代碼:
import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.io.PrintStream; import java.security.KeyFactory; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.PublicKey; import java.security.SecureRandom; import java.security.Security; import java.security.Signature; import java.security.spec.X509EncodedKeySpec; import javax.xml.bind.DatatypeConverter; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.jce.provider.JDKKeyPairGenerator; import org.bouncycastle.openssl.PEMReader; import org.bouncycastle.openssl.PEMWriter; class Verify { public static PrintStream out = System.out; public static PrintStream err = System.err; private static byte[] pubKeyData = null; public static void main(String[] args) throws Exception { if(args.length < 3) { err.println(Usage: java Verify); System.exit(1); } File pubFile = new File(args[0]); FileInputStream fin = new FileInputStream(pubFile); pubKeyData = new byte[(int) pubFile.length()]; fin.read(pubKeyData); fin.close(); out.println(verifytData:+verifyData(new File(args[1]),new File(args[2]))); } public static boolean verifyData(File signFile,File dataFile) { if(!signFile.exists()) { return false; } FileInputStream in = null; try { in = new FileInputStream(signFile); byte[] signatureBytes = new byte[(int)signFile.length()]; in.read(signatureBytes); in.close(); in = new FileInputStream(dataFile); byte[] data = new byte[(int)dataFile.length()]; in.read(data); in.close(); if (!verify(pubKeyData,signatureBytes,data)) { return false; } return true; } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } finally { try { in.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } return false; } public static boolean verify(byte[] pubKeyBytes,byte[] signatureBytes,byte[] dataBytes) throws Exception { X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(pubKeyBytes); KeyFactory keyFactory = KeyFactory.getInstance(RSA); PublicKey pubKey = keyFactory.generatePublic(pubKeySpec); //load public key Signature sg = Signature.getInstance(SHA1withRSA); sg.initVerify(pubKey); sg.update(dataBytes); //validate signature if(sg.verify(signatureBytes)){ return true; } return false; } }
使用方法:
java Verify public.bin sign.bin test.dat
在使用的過程中,簽名文件一般是和數據打包在一起的,並且在校驗的時候要保證公鑰不會被篡改,要不然校驗就沒有意義了。
當然,這裡對RSA的加密原理並沒有討論,這方面網上有很多相關的資料。
前言作為android六大布局中最為簡單的布局之一,該布局直接在屏幕上開辟出了一塊空白區域,當我們往裡面添加組件的時候,所有的組件都會放置於這塊區域的左上角;幀布局的大小
今天我們來利用Android自定義控件實現一個比較有趣的效果:滑動水波紋。先來看看最終效果圖: 圖一 效果還是很
在 Android 中,多數情況下每個程序都是在各自獨立的 Linux 進程中運行的。當一個程序或其某些部分被請求時,它的進程就“出生”了;當這個程序沒有必要再運行下去且
1.Device tree設備樹概述設備樹包含DTC(device treecompiler),DTS(device treesource和DTB(device tree