Код: Выделить всё
static func generateKeyPair(for identifier: String) -> SecKey? {
if let existingKey = getPrivateKey(for: identifier) {
log(
"RSAKeyPairHelper",
"Key already exists. Returning existing key.")
return existingKey
}
let attributes: [String: Any] = [
kSecAttrKeyType as String: kSecAttrKeyTypeRSA,
kSecAttrKeySizeInBits as String: 2048,
kSecAttrIsPermanent as String: true,
kSecAttrApplicationTag as String: getTag(for: identifier),
]
var error: Unmanaged?
guard
let privateKey = SecKeyCreateRandomKey(
attributes as CFDictionary, &error)
else { return nil }
return privateKey
}
static func getPrivateKey(for identifier: String) -> SecKey? {
let query: [String: Any] = [
kSecClass as String: kSecClassKey,
kSecAttrApplicationTag as String: getTag(for: identifier),
kSecAttrKeyType as String: kSecAttrKeyTypeRSA,
kSecReturnRef as String: true,
]
var key: AnyObject?
let status = SecItemCopyMatching(query as CFDictionary, &key)
return (status == errSecSuccess) ? (key as! SecKey?) : nil
}
static func getPublicKey(for identifier: String) -> SecKey? {
guard let privateKey = getPrivateKey(for: identifier) else {
return nil
}
return SecKeyCopyPublicKey(privateKey)
}
static func exportPublicKey(for identifier: String) -> String? {
guard let publicKey = getPublicKey(for: identifier) else { return nil }
var error: Unmanaged?
guard
let publicKeyData = SecKeyCopyExternalRepresentation(
publicKey, &error) as Data?
else { return nil }
// since android needs x509 format and we are getting PKCS#1 format
let x509Header: [UInt8] = [
0x30, 0x82, 0x01, 0x22, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01,
0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0F, 0x00
]
let x509PublicKey = Data(x509Header) + publicKeyData
return x509PublicKey.base64EncodedString()
}
static func decrypt(encryptedString: String, for identifier: String) -> String? {
log("incoming encrypted string", encryptedString)
guard let encryptedData = Data(base64Encoded: encryptedString) else {
elog("","unable to convert to data")
return nil
}
guard let privateKey = getPrivateKey(for: identifier) else {
elog("","unable to get private key")
return nil
}
var error: Unmanaged?
guard let decryptedData = SecKeyCreateDecryptedData(
privateKey, .rsaEncryptionPKCS1, encryptedData as CFData, &error
) as Data? else {
elog("","Decryption failed: \(error!.takeRetainedValue().localizedDescription)")
return nil
}
let text = String(data: decryptedData, encoding: .utf8)
log("text", "\(text), \(decryptedData)")
return text
}
< /code>
Я отправляю открытый ключ через соединение TCP, затем используйте его, как это < /p>
fun encryptWithPublicKey(publicKeyString: String, plainText: String): String? {
return try {
log("incoming public key", publicKeyString)
log("incoming data", plainText)
val publicKey =
convertBase64ToPublicKey(publicKeyString)
?: throw Exception("Invalid public key string")
val cipher = Cipher.getInstance(RSA_MODE)
cipher.init(Cipher.ENCRYPT_MODE, publicKey)
val encryptedBytes = cipher.doFinal(plainText.toByteArray())
val encryptedData = Base64.encodeToString(encryptedBytes, Base64.NO_WRAP)
log("encrypted data", encryptedData)
return encryptedData
} catch (e: Exception) {
logE("RSAKeyPairHelper", "Error while encrypting text: ${e.message}")
null
}
}
private fun convertBase64ToPublicKey(base64String: String): PublicKey? {
return try {
log("convertBase64ToPublicKey", "Public Key: $base64String")
// Decode the Base64 public key from iOS
val keyBytes = Base64.decode(
base64String,
Base64.NO_WRAP
)
val keySpec = X509EncodedKeySpec(keyBytes)
val keyFactory = KeyFactory.getInstance("RSA")
keyFactory.generatePublic(keySpec)
} catch (e: Exception) {
logE("RSAKeyPairHelper", "Error while converting string to public key: ${e.message}")
null
}
}
< /code>
Android способен шифровать данные с помощью открытого ключа iOS и отправляет зашифрованные данные через TCP -соединение. Функция расшифровки на iOS работает, но преобразование строки в конце возвращает NIL
ios журналы
[exported public Key]: MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0p5O+rnE3WNlZwWuWgT54UmqCPKidO7740RF0utjdlh/GVX7QaqMdx7iDBavqbRrbjnpFvqCuNMd7RbTBgAMohG5Mudc5Ereyj+25p/Y0Tbnc24Y70xKWn3OEs5eZ+SpzJEPxkOjwXfSMijtSC5oeEkTkmwFfjkgM0FCsx5suad5hM3vkCh8w7pP8zrg3xu8w/KJ4opsYzfTyIYeFZHxdQ9Jx1+d8UNg0MoFqfIGiifMOeCEnNDUgobJ1+W0RutWoVjo9xjW8rMdx/Nllsn4ggIAeWCMVAY1TAe4RxMDchCTVqq2CUn5QmVzDGfML+usLDXAnwZz6uT1GyGBnWyaYwIDAQAB
[incoming encrypted string]: Wf+yRn/HtZh4A6GerLP2T5gmw+6O6AsGGfgyid8IFGa+kypri7zsHQOU45HdgdLaBHzxKl+GhQPurjjZvY6hIygy0W/qXJrBnNLnxCVMWXRulk1yRS4KyEwGV0DLchK611/KL6GrSZJxDRKPN3SyBT003kHMWmw4pddJDufDXgsJInHzBbgc4F7dsPRqFRUT6yMMGXk6zyFP/xbDKwgwyoj1mf1kB3zxY3znAVmcv5JNYsQHjp5vdV20JvBdjMbaGpyUJ0XSuRquh8uG3HbZITYrofptjen2iKkqbMhc5UGsX0yKJF8UPXx/0yrg7gps3kqLDJR+zpVfNFbRrXeRYA==
[text]: nil, 92 bytes
< /code>
журналы Android < /p>
[incoming public key]: MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0p5O+rnE3WNlZwWuWgT54UmqCPKidO7740RF0utjdlh/GVX7QaqMdx7iDBavqbRrbjnpFvqCuNMd7RbTBgAMohG5Mudc5Ereyj+25p/Y0Tbnc24Y70xKWn3OEs5eZ+SpzJEPxkOjwXfSMijtSC5oeEkTkmwFfjkgM0FCsx5suad5hM3vkCh8w7pP8zrg3xu8w/KJ4opsYzfTyIYeFZHxdQ9Jx1+d8UNg0MoFqfIGiifMOeCEnNDUgobJ1+W0RutWoVjo9xjW8rMdx/Nllsn4ggIAeWCMVAY1TAe4RxMDchCTVqq2CUn5QmVzDGfML+usLDXAnwZz6uT1GyGBnWyaYwIDAQAB
[incoming data]: Test Token
[encrypted data]: Wf+yRn/HtZh4A6GerLP2T5gmw+6O6AsGGfgyid8IFGa+kypri7zsHQOU45HdgdLaBHzxKl+GhQPurjjZvY6hIygy0W/qXJrBnNLnxCVMWXRulk1yRS4KyEwGV0DLchK611/KL6GrSZJxDRKPN3SyBT003kHMWmw4pddJDufDXgsJInHzBbgc4F7dsPRqFRUT6yMMGXk6zyFP/xbDKwgwyoj1mf1kB3zxY3znAVmcv5JNYsQHjp5vdV20JvBdjMbaGpyUJ0XSuRquh8uG3HbZITYrofptjen2iKkqbMhc5UGsX0yKJF8UPXx/0yrg7gps3kqLDJR+zpVfNFbRrXeRYA==
< /code>
Данные на обоих концах (открытый ключ и зашифрованная строка Base64) одинаковы.
я попробовал без заголовка x509, но затем x509encodkeyspec < /code> будет генерировать ошибку. /p>
Что я делаю не так? < /p>
Подробнее здесь: https://stackoverflow.com/questions/794 ... id-and-ios