編輯:關於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布局之FrameLayout幀布局
前言作為android六大布局中最為簡單的布局之一,該布局直接在屏幕上開辟出了一塊空白區域,當我們往裡面添加組件的時候,所有的組件都會放置於這塊區域的左上角;幀布局的大小
Android自定義控件系列五:自定義絢麗水波紋效果
今天我們來利用Android自定義控件實現一個比較有趣的效果:滑動水波紋。先來看看最終效果圖: 圖一 效果還是很
android生命周期深入分析(二)
在 Android 中,多數情況下每個程序都是在各自獨立的 Linux 進程中運行的。當一個程序或其某些部分被請求時,它的進程就“出生”了;當這個程序沒有必要再運行下去且
msm8909+android5.1 device tree(dt) 設備樹組成和編譯
1.Device tree設備樹概述設備樹包含DTC(device treecompiler),DTS(device treesource和DTB(device tree