您的位置:首页 > 移动开发 > Android开发

Android应用开发中如何使用RSA加密算法对数据进行校验

2015-05-15 07:37 881 查看
这个世界很精彩,这个世界很无奈。是的,在互联网时代,如何保护自己的数据,如何对数据进行加密和效验就变得非常的重要。这里总结一下Android平台使用Java语言,利用RSA算法对数据进行校验的经验。

先来看下如何RSA加密算法对数据进行校验的流程:

1、首先要用openssh之类的程序生成一个私钥

2、再根据私钥生成一个公钥

3、使用私钥和公钥,对数据进行签名,得到签名文件。

4、使用公钥和签名文件就可以对数据进行校验了。

再来看下如何实现:

1、生成2048位的私钥:

[html] view
plaincopy





openssl genrsa -out private.pem 2048

2、生成公钥

使用openssh也可以生成公钥,但是在使用的过程中,发现由于格式的问题,使用openssh生成的公钥在Java中使用时总是提示异常,所以最后还是根据网上的相关资料,使用Java语言来写了程序,使用的公钥可以在Java中使用,代码如下:

GenPublic.java

[java] view
plaincopy





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 <pem file> <public file>");

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]);

}

}

使用方法:

先编译:

[html] view
plaincopy





export CLASSPATH=".:bcprov-jdk15-140.jar"

javac GenPublic.java

再使用编译的程序生成公钥:

[html] view
plaincopy





java GenPublic private.pem public.bin

用到的库可以在本文最后的链接中下载。

再来看看生成签名文件的Java代码:

Sign.java

[java] view
plaincopy





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 <pem file> <public file> <data file to sign> <signed file>");

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<data.length;i++) {

data[i] = (byte)(data[i] ^ pubKeyData[i%len]);

}

if (args.length == 4) {

FileOutputStream out = new FileOutputStream(args[3]);

out.write(signBytes);

out.close();

}

}

}

同样先编译:

[html] view
plaincopy





export CLASSPATH=".:bcprov-jdk15-140.jar"

javac Sign.java

再看看看如何生成签名文件:

java JavaSign private.pem public.bin test.dat sign.bin

这里的test.dat即是要校验的数据,sign.bin为生成的签名文件:

最后,就是如何使用公钥和签名文件进行校验数据了:

来看下面的代码:

[java] view
plaincopy





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 <public file> <sign file> <data file to 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的加密原理并没有讨论,这方面网上有很多相关的资料。

本文中用到的库可以从下面的链接中找到:
http://penguindreams.org/blog/signature-verification-between-java-and-python/comment-page-1/#comment-3664169
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android RSA 加密 校验
相关文章推荐