我正在开发一个Android应用程序,我必须使用rsa(公钥)加密一些数据(String)并解密服务器端的加密数据。
我加密后得到一个byte []数组。 我使用base64encoding(android.util.Base64)转换字节数组,默认填充。 然后在服务器端再次使用org.apache.commons.codec.binary.Base64类将字符串转换为byte []。
现在我总是将解密数据作为NULL。
我认为在byte [] - > String和String-> byte []转换中存在问题。
我在使用org.apache.commons.codec.binary.Base64时遇到问题,因为这个软件包的某些版本已包含在android库中。 当我尝试使用org.apache.commons.codec.binary.Base64作为单独的java代码进行编码和解码时。一切正常。
我该如何正确地做到这一点?
android(客户端)上的代码是,
package com.example.rsaclienttest;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import android.app.Activity;
import android.app.ProgressDialog;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Base64;
import android.view.Menu;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
public class MainActivity extends Activity {
String encSs="";
String content="";
String SSkey="";
byte[] enc;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button submit = (Button)findViewById(R.id.buttonRSA);
submit.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View arg0) {
//Generating key (128 bit) .
String seed="password";
Generator obj = new Generator(seed);
try
{
SSkey=obj.generate(); //right now i'll give only ss directly as i am having some problem with implementatin of rsa .
//now encrypt the sskey using rsa ..
rsa obj1 = new rsa();
enc = obj1.execute(getApplicationContext(), " hello ");
encSs = Base64.encodeToString(enc,Base64.DEFAULT);
//Toast.makeText(getApplicationContext(), SSkey +"\n"+encSs, Toast.LENGTH_LONG).show();
new LongOperation().execute("http://192.168.43.164:8080/rsaClient/rsaClient");
}catch(Exception e){
e.printStackTrace();
}
}
});
}
private class LongOperation extends AsyncTask<String ,Void,Void>
{
private ProgressDialog dialog = new ProgressDialog(MainActivity.this);// creating a progress dialog ..
private String error=null;
private final HttpClient client =new DefaultHttpClient();
protected void onPreExecute()
{
dialog.setMessage("Sending key to AS . Please wait ! ");
dialog.show();
}
@Override
protected Void doInBackground(String... urls) {
BufferedReader reader = null;
// Creating HTTP client
HttpClient httpClient = new DefaultHttpClient();
// Creating HTTP Post
HttpPost httpPost = new HttpPost(urls[0]);
// Building post parameters, key and value pair
List<NameValuePair> nameValuePair = new ArrayList<NameValuePair>(1);
nameValuePair.add(new BasicNameValuePair("encSS",encSs));
// Url Encoding the POST parameters
try {
httpPost.setEntity(new UrlEncodedFormEntity(nameValuePair));
}
catch (UnsupportedEncodingException e) {
// writing error to Log
e.printStackTrace();
}
// Making HTTP Request
try {
HttpResponse response = httpClient.execute(httpPost);
if(response.getStatusLine().getStatusCode()==HttpStatus.SC_OK) //SC_OK =200
{
// writing response to log
reader = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
String line=reader.readLine();
content = "";
while(line!=null)
{
content=content+line ;
line=reader.readLine();
}
reader.close();
}
} catch (ClientProtocolException e) {
//writing exception to log
e.printStackTrace();
} catch (IOException e) {
// writing exception to log
e.printStackTrace();
}
return null;
}
protected void onPostExecute(Void unused)
{
dialog.dismiss();
//if(content!="")
Toast.makeText(getApplicationContext(), content, Toast.LENGTH_LONG).show();
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
服务器端的代码是,
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.ObjectInputStream;
import java.io.PrintWriter;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.crypto.Cipher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.codec.binary.Base64;
//import sun.misc.BASE64Decoder;
/**
*
* @author root
*/
public class rsaClient extends HttpServlet {
private byte[] decryptedText;
/**
* Processes requests for both HTTP <code>GET</code> and <code>POST</code>
* methods.
*
* @param request servlet request
* @param response servlet response
* @throws ServletException if a servlet-specific error occurs
* @throws IOException if an I/O error occurs
*/
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
try (PrintWriter out = response.getWriter()) {
/* TODO output your page here. You may use following sample code. */
InputStream inStream = this.getServletContext().getResourceAsStream("/private.key");
BufferedReader reader = new BufferedReader(new InputStreamReader(inStream));
reader.close();
String encSS = request.getParameter("encSS");
byte[] decodedBytes = Base64.decodeBase64(encSS);
ObjectInputStream inputStream = new ObjectInputStream(inStream);
final PrivateKey privateKey = (PrivateKey) inputStream.readObject();
//
try {
// get an RSA cipher object and print the provider
final Cipher cipher = Cipher.getInstance("RSA");
// decrypt the text using the private key
cipher.init(Cipher.DECRYPT_MODE, privateKey);
decryptedText = cipher.doFinal(decodedBytes);
} catch (Exception ex) {
ex.printStackTrace();
}
out.println(decryptedText);
} catch (ClassNotFoundException ex) {
Logger.getLogger(rsaClient.class.getName()).log(Level.SEVERE, null, ex);
}
}
// <editor-fold defaultstate="collapsed" desc="HttpServlet methods. Click on the + sign on the left to edit the code.">
/**
* Handles the HTTP <code>GET</code> method.
*
* @param request servlet request
* @param response servlet response
* @throws ServletException if a servlet-specific error occurs
* @throws IOException if an I/O error occurs
*/
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
/**
* Handles the HTTP <code>POST</code> method.
*
* @param request servlet request
* @param response servlet response
* @throws ServletException if a servlet-specific error occurs
* @throws IOException if an I/O error occurs
*/
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
/**
* Returns a short description of the servlet.
*
* @return a String containing servlet description
*/
@Override
public String getServletInfo() {
return "Short description";
}// </editor-fold>
}
服务器上的Logcat:
javax.crypto.BadPaddingException: Decryption error
at sun.security.rsa.RSAPadding.unpadV15(RSAPadding.java:380)
at sun.security.rsa.RSAPadding.unpad(RSAPadding.java:291)
at com.sun.crypto.provider.RSACipher.doFinal(RSACipher.java:356)
at com.sun.crypto.provider.RSACipher.engineDoFinal(RSACipher.java:382)
at javax.crypto.Cipher.doFinal(Cipher.java:1922)
at rsaClient.processRequest(rsaClient.java:76)
at rsaClient.doPost(rsaClient.java:127)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:643)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:723)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:861)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:606)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
at java.lang.Thread.run(Thread.java:744)
rsa.java(用于加密):
package com.example.rsaclienttest;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.StreamCorruptedException;
import java.nio.charset.Charset;
import java.security.PublicKey;
import javax.crypto.Cipher;
import android.content.Context;
import android.content.res.AssetManager;
public class rsa{
public rsa()
{
//
}
private static final Charset UTF8_CHARSET = Charset.forName("UTF-8");
/**
* String to hold name of the encryption algorithm.
*/
public static final String ALGORITHM = "RSA";
/**
* String to hold the name of the public key file.
*/
public static final String PUBLIC_KEY_FILE = "public.key";
public static byte[] encrypt(String text, PublicKey key) {
byte[] cipherText = null;
try {
// get an RSA cipher object and print the provider
final Cipher cipher = Cipher.getInstance(ALGORITHM);
// encrypt the plain text using the public key
cipher.init(Cipher.ENCRYPT_MODE, key);
cipherText = cipher.doFinal(text.getBytes());
} catch (Exception e) {
e.printStackTrace();
}
return cipherText;
}
public byte[] execute(Context context,String originalText) throws StreamCorruptedException, IOException, ClassNotFoundException {
String s;
ObjectInputStream inputStream = null;
// Encrypt the string using the public key
AssetManager ass = context.getAssets();
inputStream=new ObjectInputStream(ass.open("public.key"));
final PublicKey publicKey = (PublicKey) inputStream.readObject();
final byte[] cipherText = encrypt(originalText, publicKey);
//return cipherText;
return cipherText;
//return s ;
// byte[] b = s.getBytes(UTF8_CHARSET);
}
}