問題一:加密結(jié)果不一致
一、問題描述
實現(xiàn)了android的藍(lán)牙對接后開始著手ios的藍(lán)牙對接,出現(xiàn)了ios加密結(jié)果與在線加密的結(jié)果一致,而android的加密結(jié)果與甲方公司的結(jié)果一致的問題。
1.android部分代碼如下:
public byte[] get3DesEncCodeCBC(byte[] byteS, byte[] key, byte[] iv) {
byte[] byteFina = null;
Cipher cipher;
try {
SecretKey desKey = new SecretKeySpec(key, "DESede");
IvParameterSpec desIV = new IvParameterSpec(iv);
cipher = Cipher.getInstance("DESede/CBC/PKCS5Padding");
cipher.init(cipher.ENCRYPT_MODE, desKey, desIV);
byteFina = cipher.doFinal(byteS);
} catch (Exception error) {
error.printStackTrace();
} finally {
cipher = null;
}
return byteFina;
}
2.ios部分代碼如下:
public static func CBCMain(op: Int, key: String, iv: String, content: String) -> String? {
// op傳1位加密,0為解密
// CCOperation(kCCEncrypt)加密 1
// CCOperation(kCCDecrypt) 解密 0
var ccop = CCOperation();
// Key
let keyData: NSData = (key as NSString).data(using: String.Encoding.utf8.rawValue)! as NSData;
let keyBytes = UnsafeRawPointer(keyData.bytes);
let keyLength = size_t(kCCKeySize3DES);
// 可選的初始化向量
let ivData: NSData = (iv as NSString).data(using: String.Encoding.utf8.rawValue)! as NSData;
let ivDataBytes = UnsafeRawPointer(ivData.bytes);
// 加密或解密的內(nèi)容
if op == 1 {
ccop = CCOperation(kCCEncrypt);
} else {
ccop = CCOperation(kCCDecrypt);
}
let data: NSData = (content as NSString).data(using: String.Encoding.utf8.rawValue)! as NSData;
let dataLength = size_t(data.length);
let dataBytes = UnsafeRawPointer(data.bytes);
// 返回數(shù)據(jù)
let cryptData = NSMutableData(length: Int(dataLength) + kCCBlockSize3DES);
let cryptPointer = UnsafeMutableRawPointer(cryptData!.mutableBytes);
let cryptLength = size_t(cryptData!.length);
// 特定的幾個參數(shù)
let operation: CCOperation = UInt32(ccop);
let algoritm: CCAlgorithm = UInt32(kCCAlgorithm3DES);
let options: CCOptions = UInt32(kCCOptionPKCS7Padding);
var numBytesCrypted :size_t = 0;
let cryptStatus = CCCrypt(operation, // 加密還是解密
algoritm, // 算法類型
options, // 密碼塊的設(shè)置選項
keyBytes, // 秘鑰的字節(jié)
keyLength, // 秘鑰的長度
ivDataBytes, // 可選初始化向量的字節(jié)
dataBytes, // 加解密內(nèi)容的字節(jié)
dataLength, // 加解密內(nèi)容的長度
cryptPointer, // output data buffer
cryptLength, // output data length available
&numBytesCrypted); // real output data length
if UInt32(cryptStatus) == UInt32(kCCSuccess) {
cryptData!.length = Int(numBytesCrypted);
if op == 1 {
// 返回加密的數(shù)據(jù)
let hexStr = DataUtils.nsDataToHex(data: cryptData!);
return hexStr;
} else {
// 返回解密的數(shù)據(jù)
let hexStr = DataUtils.nsDataToHex(data: cryptData!);
return hexStr;
}
}
return nil;
}
二、問題解決
重新看了一遍android加密調(diào)用部分的代碼,使用了十六進(jìn)制字符串轉(zhuǎn)byte數(shù)組的方法:
由于是對藍(lán)牙數(shù)據(jù)進(jìn)行加密,所以傳入的字符串為十六進(jìn)制,在ios代碼中使用:
(content as NSString).data(using: String.Encoding.utf8.rawValue)! as NSData;
是錯誤的,改為十六進(jìn)制字符串的轉(zhuǎn)換方法:
let keyData: NSData = Data.init(hex: key) as NSData;
最終獲取到了正確的加密結(jié)果。
問題二:解密結(jié)果不一致
一、問題描述
在解決完加密結(jié)果不一致的問題后,發(fā)現(xiàn)ios的解密結(jié)果也與android結(jié)果不一致。文章來源:http://www.zghlxwxcb.cn/news/detail-417236.html
二、問題解決
在著手解決加密結(jié)果不一致的問題時,有篇文章中寫到android對key的處理,若key為16字節(jié),則會將前8字節(jié)拼接到key末尾,組成24字節(jié)的key,而ios存在16字節(jié)與24字節(jié)兩種長度的key值,若傳入的key為16字節(jié),則會直接使用16字節(jié)的key。所以在key傳入時,對其做長度的判斷,若為16字節(jié)則進(jìn)行拼接即可解決。文章來源地址http://www.zghlxwxcb.cn/news/detail-417236.html
ios部分代碼如下:
public static func decryptionCBC(key: String, iv: String, content: String) -> String? {
// 密鑰處理
var keyStr = [String]();
if key.length() == 32 {
keyStr.append(key);
keyStr.append(key.substr(index: 0, length: 16));
}
let keyData: NSData = Data.init(hex: keyStr.joined()) as NSData;
let keyBytes = UnsafeRawPointer(keyData.bytes);
let keyLength = size_t(kCCKeySize3DES);
// 可選的初始化向量
let ivData: NSData = Data.init(hex: iv) as NSData;
let ivDataBytes = UnsafeRawPointer(ivData.bytes);
// 加密或解密的內(nèi)容
let ccop = CCOperation(kCCDecrypt);
let data = Data.init(hex: content) as NSData;
let dataLength = size_t(data.length);
let dataBytes = UnsafeRawPointer(data.bytes);
// 返回數(shù)據(jù)
let cryptData = NSMutableData(length: Int(dataLength) + kCCBlockSize3DES);
let cryptPointer = UnsafeMutableRawPointer(cryptData!.mutableBytes);
let cryptLength = size_t(cryptData!.length);
// 特定的幾個參數(shù)
let operation: CCOperation = UInt32(ccop);
let algoritm: CCAlgorithm = UInt32(kCCAlgorithm3DES);
let options: CCOptions = UInt32(kCCOptionPKCS7Padding);
var numBytesCrypted :size_t = 0;
let cryptStatus = CCCrypt(operation, // 加密還是解密
algoritm, // 算法類型
options, // 密碼塊的設(shè)置選項
keyBytes, // 秘鑰的字節(jié)
keyLength, // 秘鑰的長度
ivDataBytes, // 可選初始化向量的字節(jié)
dataBytes, // 加解密內(nèi)容的字節(jié)
dataLength, // 加解密內(nèi)容的長度
cryptPointer, // output data buffer
cryptLength, // output data length available
&numBytesCrypted); // real output data length
if UInt32(cryptStatus) == UInt32(kCCSuccess) {
cryptData!.length = Int(numBytesCrypted);
let hexStr = DataUtils.nsDataToHex(data: cryptData!);
return hexStr;
}
return nil;
}
附一:測試通過后的IOS SWIFT 3DES加密解密代碼
/**
- CBC算法加密
- parameter key: 密鑰
- parameter iv: 偏移量
- parameter content: 加密數(shù)據(jù)
- returns: string
*/
public static func encryptionCBC(key: String, iv: String, content: String) -> String? {
// 密鑰處理
var keyStr = [String]();
if key.length() == 32 {
keyStr.append(key);
keyStr.append(key.substr(index: 0, length: 16));
}
let keyData: NSData = Data.init(hex: keyStr.joined()) as NSData;
let keyBytes = UnsafeRawPointer(keyData.bytes);
let keyLength = size_t(kCCKeySize3DES);
// 可選的初始化向量
let ivData: NSData = Data.init(hex: iv) as NSData;
let ivDataBytes = UnsafeRawPointer(ivData.bytes);
// 加密或解密的內(nèi)容
let ccop = CCOperation(kCCEncrypt);
let data = Data.init(hex: content) as NSData;
let dataLength = size_t(data.length);
let dataBytes = UnsafeRawPointer(data.bytes);
// 返回數(shù)據(jù)
let cryptData = NSMutableData(length: Int(dataLength) + kCCBlockSize3DES);
let cryptPointer = UnsafeMutableRawPointer(cryptData!.mutableBytes);
let cryptLength = size_t(cryptData!.length);
// 特定的幾個參數(shù)
let operation: CCOperation = UInt32(ccop);
let algoritm: CCAlgorithm = UInt32(kCCAlgorithm3DES);
let options: CCOptions = UInt32(kCCOptionPKCS7Padding);
var numBytesCrypted :size_t = 0;
let cryptStatus = CCCrypt(operation, // 加密還是解密
algoritm, // 算法類型
options, // 密碼塊的設(shè)置選項
keyBytes, // 秘鑰的字節(jié)
keyLength, // 秘鑰的長度
ivDataBytes, // 可選初始化向量的字節(jié)
dataBytes, // 加解密內(nèi)容的字節(jié)
dataLength, // 加解密內(nèi)容的長度
cryptPointer, // output data buffer
cryptLength, // output data length available
&numBytesCrypted); // real output data length
if UInt32(cryptStatus) == UInt32(kCCSuccess) {
cryptData!.length = Int(numBytesCrypted);
let hexStr = DataUtils.nsDataToHex(data: cryptData!);
return hexStr;
}
return nil;
}
/**
- CBC算法解密
- parameter key: 密鑰
- parameter iv: 偏移量
- parameter content: 加密數(shù)據(jù)
- returns: string
*/
public static func decryptionCBC(key: String, iv: String, content: String) -> String? {
// 密鑰處理
var keyStr = [String]();
if key.length() == 32 {
keyStr.append(key);
keyStr.append(key.substr(index: 0, length: 16));
}
let keyData: NSData = Data.init(hex: keyStr.joined()) as NSData;
let keyBytes = UnsafeRawPointer(keyData.bytes);
let keyLength = size_t(kCCKeySize3DES);
// 可選的初始化向量
let ivData: NSData = Data.init(hex: iv) as NSData;
let ivDataBytes = UnsafeRawPointer(ivData.bytes);
// 加密或解密的內(nèi)容
let ccop = CCOperation(kCCDecrypt);
let data = Data.init(hex: content) as NSData;
let dataLength = size_t(data.length);
let dataBytes = UnsafeRawPointer(data.bytes);
// 返回數(shù)據(jù)
let cryptData = NSMutableData(length: Int(dataLength) + kCCBlockSize3DES);
let cryptPointer = UnsafeMutableRawPointer(cryptData!.mutableBytes);
let cryptLength = size_t(cryptData!.length);
// 特定的幾個參數(shù)
let operation: CCOperation = UInt32(ccop);
let algoritm: CCAlgorithm = UInt32(kCCAlgorithm3DES);
let options: CCOptions = UInt32(kCCOptionPKCS7Padding);
var numBytesCrypted :size_t = 0;
let cryptStatus = CCCrypt(operation, // 加密還是解密
algoritm, // 算法類型
options, // 密碼塊的設(shè)置選項
keyBytes, // 秘鑰的字節(jié)
keyLength, // 秘鑰的長度
ivDataBytes, // 可選初始化向量的字節(jié)
dataBytes, // 加解密內(nèi)容的字節(jié)
dataLength, // 加解密內(nèi)容的長度
cryptPointer, // output data buffer
cryptLength, // output data length available
&numBytesCrypted); // real output data length
if UInt32(cryptStatus) == UInt32(kCCSuccess) {
cryptData!.length = Int(numBytesCrypted);
let hexStr = DataUtils.nsDataToHex(data: cryptData!);
return hexStr;
}
return nil;
}
附二:測試通過后的ANDROID 3DES加密解密代碼
一、Des3Utils.java
/**
* CBC算法加密
*
* @param key
* @param content
* @return
*/
public static String encryptionCBC(String key, String iv, String content) {
Des3EncryptUtils des = new Des3EncryptUtils();
byte[] bye = des.get3DesEncCodeCBC(DataUtils.hexStrToByteArray(content), DataUtils.hexStrToByteArray(key), DataUtils.hexStrToByteArray(iv));
return HexUtils.toString(bye).trim();
}
/**
* CBC算法解密
*
* @param key
* @param content
* @return
*/
public static byte[] decryptionCBC(String key, String iv, String content) {
Des3EncryptUtils des = new Des3EncryptUtils();
return des.get3DesDesCodeCBC(DataUtils.hexStrToByteArray(content), DataUtils.hexStrToByteArray(key), DataUtils.hexStrToByteArray(iv));
}
二、DataUtils.java
/**
* 16進(jìn)制字符串轉(zhuǎn)byte數(shù)組
*
* @param hexStr
* @return
*/
public static byte[] hexStrToByteArray(String hexStr) {
if (hexStr == null) {
return null;
}
if (hexStr.length() == 0) {
return new byte[0];
}
byte[] byteArray = new byte[hexStr.length() / 2];
for (int i = 0; i < byteArray.length; i++) {
String subStr = hexStr.substring(2 * i, 2 * i + 2);
byteArray[i] = ((byte) Integer.parseInt(subStr, 16));
}
return byteArray;
}
三、Des3EncryptUtils.java
/**
* CBC算法加密(帶向量)
*
* @param byteS
* @return
*/
public byte[] get3DesEncCodeCBC(byte[] byteS, byte[] key, byte[] iv) {
byte[] byteFina = null;
Cipher cipher;
try {
SecretKey desKey = new SecretKeySpec(key, "DESede");
IvParameterSpec desIV = new IvParameterSpec(iv);
cipher = Cipher.getInstance("DESede/CBC/PKCS5Padding");
cipher.init(cipher.ENCRYPT_MODE, desKey, desIV);
byteFina = cipher.doFinal(byteS);
} catch (Exception error) {
error.printStackTrace();
} finally {
cipher = null;
}
return byteFina;
}
/**
* CBC算法解密(帶向量)
*
* @param byteS
* @return
*/
public byte[] get3DesDesCodeCBC(byte[] byteS, byte[] key, byte[] iv) {
byte[] byteFina = null;
Cipher cipher;
try {
SecretKey desKey = new SecretKeySpec(key, "DESede");
IvParameterSpec desIV = new IvParameterSpec(iv);
cipher = Cipher.getInstance("DESede/CBC/PKCS5Padding");
cipher.init(cipher.DECRYPT_MODE, desKey, desIV);
byteFina = cipher.doFinal(byteS);
} catch (Exception error) {
error.printStackTrace();
} finally {
cipher = null;
}
return byteFina;
}
到了這里,關(guān)于【ios】【android】3DES_CBC_PKCS5Padding加密、解密問題(附完整代碼)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!