php rsa 加密

今天我来说下如何使用RSA方式进行加密解密

一、生成公钥和私钥;

使用OpenSSL就可以,一般Linux和mac有自带的;windows的可自行安装;

通过如下命令生成;

注:

RSA非对称加密内容长度有限制,1024位key的最多只能加密127位数据,如果加密字符串过长请使用2048

momodeMBP:~ momo$ openssl genrsa -out rsa_private_key.pem 1024(去掉1024默认生成的是2048位)
Generating RSA private key, 1024 bit long modulus
 
.....++++++
 
............................++++++
 
e is 65537 (0x10001)
 
momodeMBP:~ momo$ openssl pkcs8 -topk8 -inform PEM -in rsa_private_key.pem -outform PEM -nocrypt -out private_key.pem
 
momodeMBP:~ momo$ openssl rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem
 
writing RSA key
 
momodeMBP:~ momo$

第一条命令生成原始 RSA私钥文件 rsa_private_key.pem;

第二条命令将原始 RSA私钥转换为 pkcs8格式;

第三条生成RSA公钥 rsa_public_key.pem;

从上面看出通过私钥能生成对应的公钥,因此我们将私钥private_key.pem用在服务器端,rsa_public_key.pem给客户端ios、Android、外部合作方;

这里我们来说下服务器端的处理方式:

<?php
 
$private_key=file_get_contents('private_key.pem'); //读取私钥
 
$public_key=file_get_contents('rsa_public_key.pem'); //读取公钥
 
$pi_key =  openssl_pkey_get_private($private_key);//这个函数可用来判断私钥是否是可用的,可用返回资源id Resource id
 
$pu_key = openssl_pkey_get_public($public_key);//这个函数可用来判断公钥是否是可用的
 
$data = 'method=medicool.user.detail&nonce_str=607673¶meters={"test":"2458"}&partnerid=test';//原始数据
 
echo "private key encrypt:\n";
 
openssl_private_encrypt($data,$encrypted,$pi_key);//私钥加密
 
$encrypted = base64_encode($encrypted);//加密后的内容通常含有特殊字符,需要编码转换下,在网络间通过url传输时要注意base64编码是否是url安全的
 
$encrypted=urlencode($encrypted);
 
echo $encrypted,"\n"; //输出私钥加密后的字符串数据
 
echo "public key decrypt:\n";
 
openssl_public_decrypt(base64_decode(urldecode($encrypted)),$decrypted,$pu_key);//私钥加密的内容通过公钥可用解密出来
 
echo $decrypted,"\n"; //通过公钥解密后的字符串数据
 
echo "---------------------------------------\n";
 
echo "public key encrypt:\n";
 
openssl_public_encrypt($data,$encrypted,$pu_key);//公钥加密
 
$encrypted = (base64_encode($encrypted));
 
$encrypted=urlencode($encrypted);
 
echo $encrypted,"\n";//通过公钥加密后的字符串数据
 
echo "private key decrypt:\n";
 
openssl_private_decrypt(base64_decode(urldecode($encrypted)),$decrypted,$pi_key);//私钥解密
 
echo $decrypted,"\n"; //通过私钥解密后的字符串数据
 
?>

下面是ios的对接demo:


//获得筛选标签
-(void)requesYikuData{
 
    //随机生成6位数
 
    int num = (arc4random() % 1000000);
 
    NSString * randomNumber = [NSString stringWithFormat:@"%.6d", num];
 
    NSLog(@"%@", randomNumber);
 
    //遵循约定,生成签名
 
    //JSON转换之后有回车空格以及中文转义问题 导致签名无法验证
 
    //文字转义放在客户端执行
 
    NSString * searchName ="头孢";//搜索名称
 
    int page = 1;//页码
 
    NSString *string =[NSString stringWithFormat:@"{\"cpage\":%d,\"keywords\":\"%@\"}",page,searchName];
 
    //3.未加密签名组成字符串
 
    NSString * str1 = [NSString stringWithFormat:@"method=medicool.drug.search&nonce_str=%@¶meters=%@&partnerid=test",randomNumber,string];
 
    //4;对3字符串根据公钥RSA加密;
 
    NSString *rsaStr = [RSAEncryptor encryptString:[str1 lowercaseString] publicKey:YIKUPUBLICKEY];
 
    NSLog(@"RSA加密后字符串%@",rsaStr);
 
    //5;对4结果进行base64_encode
 
    NSData * encodeData = [rsaStr dataUsingEncoding:NSUTF8StringEncoding];
 
    //    encodeData = [encodeData base64EncodedDataWithOptions:0];
 
    NSString *base64Str = [[NSString alloc] initWithData:encodeData encoding:NSUTF8StringEncoding];
 
    //6;对5结果进行urlencode;
 
    NSString * signStr =  [RSAEncryptor encodeString:base64Str];
 
    NSLog(@"urlencode后字符串%@",signStr);
 
    //请求的url
 
    NSString * urStr = @"http://extratest.cn/Apidrug/medisearch";
 
 
    AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
    manager.responseSerializer.acceptableContentTypes =[NSSet setWithObjects:@"text/html",@"text/plain",@"text/json",@"application/json",nil];
 
    manager.requestSerializer = [AFHTTPRequestSerializer serializer];
 
    manager.responseSerializer = [AFHTTPResponseSerializer serializer];
 
    NSDictionary* URLParameters = @{
 
           @"cpage":@1,
           @"keywords":@"头孢",
           @"method":@"medicool.drug.search",
           @"nonce_str":randomNumber,
           @"partnerid":@"test",
           @"sign":signStr,
       };
 
  NSMutableURLRequest* request = [[AFHTTPRequestSerializer serializer] requestWithMethod:@"POST" URLString:urStr parameters:URLParameters error:NULL];
 AFHTTPRequestOperation *operation = [manager HTTPRequestOperationWithRequest:request                                                                 success:^(AFHTTPRequestOperation *operation, id responseObject) {                                                       NSLog(@"HTTP Response Status Code: %ld", [operation.response statusCode]);
                                                                            NSLog(@"HTTP Response Body: %@", responseObject);
                                                                            NSDictionary *tempDictQueryDiamond = [NSJSONSerialization JSONObjectWithData:responseObject options:0 error:nil];
                                                                           NSLog(@"%@",tempDictQueryDiamond);
                                                                         } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
                                                                        NSLog(@"HTTP Request failed: %@", error);
                                                                      }];
    [manager.operationQueue addOperation:operation];
}

Android对接demo:

主项目

package medicool.com.medicool;
 
 
 
import android.support.v7.app.AppCompatActivity;
 
import android.os.Bundle;
 
import android.widget.ListView;
 
import android.widget.SearchView;
 
import android.widget.TextView;
 
 
import java.util.HashMap;
 
 
 
public class MainActivity extends AppCompatActivity {
 
    private final String url = "http://extratest.meditool.cn/Apidrug/medisearch";
 
    private final String search_method = "medicool.drug.search";
 
 
 
    private SearchView searchView;
 
    private TextView textView;
 
 
    private int cpage = 1;
 
    private String sign;
 
    //POST数据
 
    HashMap<String, String> args_jsondata = new HashMap<>();
 
    //签名原数据
 
    HashMap<String, Object> args_sign = new HashMap<>();
 
 
 
    @Override
 
    protected void onCreate(Bundle savedInstanceState) {
 
        super.onCreate(savedInstanceState);
 
        setContentView(R.layout.activity_main);
 
 
 
        /**
         * method 请求方法名
         nonce_str 随机字符串
         partnerid 合作方指定字符串
         sign 签名
         cpage 请求页码
         keywords 搜索关键词
         */
 
        args_jsondata.put("method", search_method);
 
        args_jsondata.put("nonce_str", "123456");
 
        args_jsondata.put("partnerid", Sign.PARTNERID);
 
 
 
        textView = (TextView) findViewById(R.id.textView);
 
        searchView = (SearchView) findViewById(R.id.searchView);
 
        searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
 
            @Override
 
            public boolean onQueryTextSubmit(String query) {
 
                if ("".equals(query)) {
 
                    return false;
 
                }
 
 
 
                //这里注意下手动排序,即 医库合作约定
 
                // 1;将业务请求参数名按照字母升序存入数组
 
                args_sign.put("cpage", cpage);
 
                args_sign.put("keywords", query.trim());
 
 
 
                //对args_sign签名
 
                try {
 
                    sign = Sign.getSign(MainActivity.this, search_method, "123456", args_sign);
 
                } catch (Exception e) {
 
                    e.printStackTrace();
 
                }
 
 
 
                //参数补全
 
                args_jsondata.put("sign", sign);
 
                args_jsondata.put("cpage", cpage + "");
 
                args_jsondata.put("keywords", query.trim());
 
 
 
                new Thread(new Runnable() {
 
                    @Override
 
                    public void run() {
 
                        final String result = HttpUtils.getData(url, args_jsondata);
 
                        runOnUiThread(new Runnable() {
 
                            @Override
 
                            public void run() {
 
                                textView.setText(result);
 
                            }
 
                        });
 
                    }
 
                }).start();
 
 
 
                return false;
 
            }
 
 
            @Override
 
            public boolean onQueryTextChange(String newText) {
 
                return false;
 
            }
 
        });
 
    }
 
}

Sign类:

package medicool.com.medicool;
 
import android.content.Context;
 
import android.net.Uri;
 
import android.util.Base64;
 
import org.json.JSONException;
 
import org.json.JSONObject;
 
import java.util.HashMap;
 
import java.util.Map;
 
 
 
public class Sign {
 
    //固定
 
    public static final String PARTNERID = "medicoolgandan2017";
 
 
 
    public static String getSign(Context context, String method, String nonce_str, HashMap<String, Object> parameters) throws Exception {
 
        String sign;
 
        JSONObject jsonObject = new JSONObject();
 
        String j_parameters = "";
 
        //对parameters进行json_encode处理
 
        try {
 
            if (parameters != null && !parameters.isEmpty()) {
 
                for (Map.Entry<String, Object> entry : parameters.entrySet()) {
 
                    jsonObject.put(entry.getKey(), entry.getValue());
 
                }
 
                j_parameters = jsonObject.toString();
 
            }
 
        } catch (JSONException e) {
 
            e.printStackTrace();
 
        }
 
 
 
        //拼接参数method=$method&nonce_str=$nonce_str¶meters=$parameters&partnerid=$partnerid
 
        StringBuffer stringBuffer = new StringBuffer();
 
        stringBuffer.append("method=").append(method + "&").append("nonce_str=").append(nonce_str + "&").append("parameters=").append(j_parameters + "&").append("partnerid=" + PARTNERID);
 
 
 
        //RSA加密
 
        byte[] bytes = RsaUtils.encryptData(stringBuffer.toString().getBytes(), context);
 
 
        //base64_encodec
 
        sign = Base64.encodeToString(bytes, Base64.DEFAULT);
 
 
 
        //urlencode
 
        sign = Uri.encode(sign);
 
 
        return sign;
 
    }
 
 
}

RsaUtils类:

package medicool.com.medicool;
 
 
 
import android.content.Context;
 
import android.util.Base64;
 
 
 
import java.io.InputStream;
 
import java.security.KeyFactory;
 
import java.security.PublicKey;
 
import java.security.spec.X509EncodedKeySpec;
 
 
 
import javax.crypto.Cipher;
 
 
 
public class RsaUtils {
 
    private static String RSA = "RSA";
 
    private static final String ECB_PKCS1_PADDING = "RSA/ECB/PKCS1Padding";
 
 
 
    public static byte[] encryptData(byte[] data, Context context) {
 
        byte[] resultBytes = null;
 
        try {
 
            PublicKey publicKey = loadPublicKey(context);
 
            Cipher cipher = Cipher.getInstance(ECB_PKCS1_PADDING);
 
            cipher.init(Cipher.ENCRYPT_MODE, publicKey);
 
            resultBytes = cipher.doFinal(data);
 
        } catch (Exception e) {
 
            e.printStackTrace();
 
        }
 
 
 
        return resultBytes;
 
    }
 
 
 
    private static PublicKey loadPublicKey(Context context) throws Exception {
 
        try {
 
            PublicKey publicKey;
 
            byte[] keyBytes = Base64.decode(readFile(context, "rsa_public_key.pem"), Base64.DEFAULT);
 
            X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
 
            KeyFactory keyFactory = KeyFactory.getInstance(RSA);
 
            publicKey = keyFactory.generatePublic(keySpec);
 
            return publicKey;
 
        } catch (Exception e) {
 
            throw new Exception("密钥数据读取错误");
 
        }
 
    }
 
 
 
    private static String readFile(Context context, String file) {
 
        int len;
 
        byte[] buf;
 
        String grammar = "";
 
        try {
 
            InputStream in = context.getAssets().open(file);
 
            len = in.available();
 
            buf = new byte[len];
 
            in.read(buf, 0, len);
 
            grammar = new String(buf, "utf-8");
 
        } catch (Exception e) {
 
            e.printStackTrace();
 
        }
 
        return grammar;
 
    }
}

HttpUtils类:


package medicool.com.medicool;
 
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
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 org.apache.http.params.CoreConnectionPNames;
import org.apache.http.util.EntityUtils;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
 
public class HttpUtils {
    public static String getData(String url, HashMap<String, String> params) {
 
        HttpPost post = new HttpPost(url);
 
        HttpClient httpclient = new DefaultHttpClient();
httpclient.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 30000);
httpclient.getParams().setParameter(CoreConnectionPNames.SO_TIMEOUT, 30000);
        ArrayList<NameValuePair> paramPairs = new ArrayList<>();
        if (params != null && !params.isEmpty()) {
            for (Map.Entry<String, String> entry : params.entrySet()) {
                paramPairs.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
            }
        }
 
        try {
            post.setEntity(new UrlEncodedFormEntity(paramPairs, "UTF-8"));
        } catch (UnsupportedEncodingException e) {
            return "";
        }
 
        try {
            HttpResponse response;
            response = httpclient.execute(post);
            String inf;
            if (response.getStatusLine().getStatusCode() == 200) {// 判断响应状态码
                inf = EntityUtils.toString(response.getEntity());
                return inf;
            }
        } catch (Exception e) {
 
            e.printStackTrace();
        }
        return "";
    }
}

猜你喜欢

转载自blog.csdn.net/liuqun0319/article/details/86697914