加密字符串PHP-serverside的代码。 我使用PKCS8而不是PKCS1,以便我可以在Android端解密。
加密的代码如下: 我使用的是phpseclib。
include('libs/PHPSecLib/Crypt/RSA.php');
...用于查找存储在数据库中的公钥和私钥的代码...
$rsa = new Crypt_RSA();
$rsa->loadKey($row['pref_pub_key']); // public key stored in MySQL BLOB.
$plaintext = 'Testing 123';
$rsa->setEncryptionMode(CRYPT_RSA_ENCRYPTION_PKCS8); //USE PKCS8
$ciphertext = $rsa->encrypt($plaintext);
echo $ciphertext;
$rsa->loadKey($row['pref_priv_key']); // private key stored in MySQL BLOB
echo $rsa->decrypt($ciphertext);
$query = "UPDATE preferences SET pref_license = ?;
//execute query to store the encrypted text in pref_license BLOB field.
try {
$stmt = $db->prepare($query);
$stmt->bindParam(1,$ciphertext);
$stmt->bindParam(2,$ref);
$db->errorInfo();
$result = $stmt->execute();
}
catch (PDOException $ex) {
$response["success"] = 0;
$response["message"] = "Database Error. Couldn't update Pref post with License!" . $ex->getMessage();
echo $response["message"];
die(json_encode($response));
}
我基本上加密了字符串,并将其存储在BLOB字段中,供以后参考。
我生成Private Public KEYPAIR并以下列方式存储在BLOB中,并将私钥发送到Android设备:
include('libs/PHPSecLib/Crypt/RSA.php');
$rsa = new Crypt_RSA();
$rsa->setPrivateKeyFormat(CRYPT_RSA_PRIVATE_FORMAT_PKCS8);
$rsa->setPublicKeyFormat(CRYPT_RSA_PUBLIC_FORMAT_PKCS8);
extract($rsa->createKey());
//echo $privatekey . '<br/><br/>' . $publickey; //I can see that it worked!
if (!empty($_POST)) {
//initial update query to store the keys in BLOBS on SERVER MYSQL
$query = "UPDATE preferences SET pref_priv_key = ?, pref_pub_key = ?
WHERE pref_device_serial = ?";
//execute query
try {
$stmt = $db->prepare($query);
$stmt->bindParam(1,$privatekey);
$stmt->bindParam(2,$publickey);
$stmt->bindParam(3,$_POST['p_device_serial']);
$db->errorInfo();
$result = $stmt->execute();
}
catch (PDOException $ex) {
$response["success"] = 0;
$response["message"] = "Database Error. Couldn't update Pref post!" . $ex->getMessage();
die(json_encode($response));
}
}
//then I send the $privatekey to the Android device and save it there.
//to then later decrypt the serverside encrypted string.
$response["success"] = 1;
$response["pk"] = $privatekey;
$response["message"] = "Key Pair successfully generated.";
echo json_encode($response);
在Android设备上,我使用ans AsyncTask来请求加密字符串,然后从本地sqlite blob字段读取PrivateKey,并尝试解密字符串:
class GetLicense extends AsyncTask<String, String, String> {
@Override
protected void onPreExecute() {
super.onPreExecute();
pDialog = new ProgressDialog(LicenseActivity.this);
pDialog.setMessage("Retrieving License Data...");
pDialog.setIndeterminate(false);
pDialog.setCancelable(true);
pDialog.show();
}
@Override
protected String doInBackground(String... args) {
int success;
String elicense;
try {
getPref = LicenseActivity.this.openOrCreateDatabase("aaa.db", Context.MODE_PRIVATE, null);
Cursor c = getPref.rawQuery("SELECT * FROM preferences", null);
Log.d("request!", "starting");
if (c != null) {
if (c.moveToFirst()) {
do {
String Preferences_Id = c.getString(c.getColumnIndex(SupaAttendDb.KEY_ROWID));
String Preferences_UUID = c.getString(c.getColumnIndex(SupaAttendDb.KEY_Preferences_PREFUUID));
String Preferences_Device_Serial = c.getString(c.getColumnIndex(SupaAttendDb.KEY_Preferences_PREFDEVICESERIAL));
sPK = c.getString(c.getColumnIndex(SupaAttendDb.KEY_Preferences_PREFPK));
// Building Parameters
List<NameValuePair> params = new ArrayList<NameValuePair>();
params.add(new BasicNameValuePair("p_uuid", Preferences_UUID));
try {
//Get Encrypted License from server
JSONObject json = jsonParser.makeHttpRequest(
GET_LICENSE_URL, "POST", params);
// full json response
// json success element
success = json.getInt(TAG_SUCCESS);
if (success == 1) {
sData = json.getString(TAG_LICENSE);
..然后我将许可证保存到Android SQLite。代码不需要...... 在onPostExecute中,我格式化PrivateKey,然后尝试解密sData,但返回不正确的数据,而不是'Testing 123'。
protected void onPostExecute(String file_url) {
pDialog.dismiss();
String privKeyPEM = sPK.replace("-----BEGIN PRIVATE KEY-----\r\n", "");
privKeyPEM = privKeyPEM.replace("-----END PRIVATE KEY-----", "");
byte[] b = Base64.decode(privKeyPEM,Base64.DEFAULT);
KeyFactory keyFactory = null;
try {
keyFactory = KeyFactory.getInstance("RSA");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(b); //This decodes properly without any exceptions.
PrivateKey privateKey2 = null;
try {
privateKey2 = keyFactory.generatePrivate(privateKeySpec);
} catch (InvalidKeySpecException e) {
e.printStackTrace();
}
byte[] decryptedData = null;
Cipher cipher = null;
try {
cipher = Cipher.getInstance("RSA");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
}
try {
cipher.init(Cipher.DECRYPT_MODE,privateKey2);
} catch (InvalidKeyException e) {
e.printStackTrace();
}
byte[] sD = Base64.decode(sData, Base64.DEFAULT);// Here I try to get the encrypted string retrieved from server into a byte[].
try {
decryptedData = cipher.doFinal(sD); // no errors, but I get the incorrect unencrypted string.
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
}
if (decryptedData != null){
String decrypted = new String(decryptedData);
//decryptedData = Base64.encode(decryptedData,Base64.DEFAULT);
Toast.makeText(LicenseActivity.this, decrypted, Toast.LENGTH_LONG).show();
}
}
}
我意识到我只是在最后一段代码中做了一些愚蠢的事情,我尝试解码加密字符串,然后解密它。 希望你能指出我正确的方向,并为长篇大论而感到遗憾。
哦,是的,在您提问之前,我使用以下PHP从服务器检索许可证:
require("config.inc.php");
if (!empty($_POST)) {
//initial query
$query = "SELECT pref_uuid, pref_license, pref_device_serial FROM preferences WHERE pref_uuid = :p_uuid";
$query_params = array(':p_uuid' => $_POST['p_uuid']);
//execute query
try {
$stmt = $db->prepare($query);
$db->errorInfo();
$result = $stmt->execute($query_params);
}
catch (PDOException $ex) {
$response["success"] = 0;
$response["message"] = "Database Error. Couldn't retrieve License details!" . $ex->getMessage();
die(json_encode($response));
}
if(!$result) {
$response["success"] = 0;
$response["message"] = "Database Error. Couldn't return Licenses!" . $ex->getMessage();
die(json_encode($response));
}
$row = $stmt->fetch(PDO::FETCH_ASSOC);
$response["license"] = base64_encode($row['pref_license']); // I encode it here before I send the encrypted string off to android device.
$response["message"] = "License Record successfully retrieved";
$response["success"] = 1;
echo json_encode($response);
}
答案 0 :(得分:0)
好的,感谢Maarten Bodewes,我回到服务器端的PKCS#1,然后无法按预期在Android端使用它。我发现SpongyCastle library,并且能够从PrivateKey中提取Modulus和privateExponent,然后我能够成功解密加密的字符串。感谢MAARTEN !!!!