how to encrypt and decrypt a String(Plain Text) with RSA public key in ios, swift
Hope this will help you:
let serverPublicKey = "Some text with key"
let data2 = Data.init(base64Encoded: serverPublicKey)
let keyDict:[NSObject:NSObject] = [
kSecAttrKeyType: kSecAttrKeyTypeRSA,
kSecAttrKeyClass: kSecAttrKeyClassPublic,
kSecAttrKeySizeInBits: NSNumber(value: 2048),
kSecReturnPersistentRef: true as NSObject
]
let publickeysi = SecKeyCreateWithData(data2! as CFData, keyDict as CFDictionary, nil)
//Encrypt a string with the public key
let message = "This is my message."
let blockSize = SecKeyGetBlockSize(publickeysi!)
var messageEncrypted = [UInt8](repeating: 0, count: blockSize)
var messageEncryptedSize = blockSize
var status: OSStatus!
status = SecKeyEncrypt(publickeysi!, SecPadding.PKCS1, message, message.characters.count, &messageEncrypted, &messageEncryptedSize)
if status != noErr {
print("Encryption Error!")
return
}
RSA Encryption function in Swift 4 from Public Key string
You can do like this way...
static func encrypt(string: String, publicKey: String?) -> String? {
guard let publicKey = publicKey else { return nil }
let keyString = publicKey.replacingOccurrences(of: "-----BEGIN PUBLIC KEY-----\n", with: "").replacingOccurrences(of: "\n-----END PUBLIC KEY-----", with: "")
guard let data = Data(base64Encoded: keyString) else { return nil }
var attributes: CFDictionary {
return [kSecAttrKeyType : kSecAttrKeyTypeRSA,
kSecAttrKeyClass : kSecAttrKeyClassPublic,
kSecAttrKeySizeInBits : 2048,
kSecReturnPersistentRef : kCFBooleanTrue] as CFDictionary
}
var error: Unmanaged<CFError>? = nil
guard let secKey = SecKeyCreateWithData(data as CFData, attributes, &error) else {
print(error.debugDescription)
return nil
}
return encrypt(string: string, publicKey: secKey)
}
static func encrypt(string: String, publicKey: SecKey) -> String? {
let buffer = [UInt8](string.utf8)
var keySize = SecKeyGetBlockSize(publicKey)
var keyBuffer = [UInt8](repeating: 0, count: keySize)
// Encrypto should less than key length
guard SecKeyEncrypt(publicKey, SecPadding.PKCS1, buffer, buffer.count, &keyBuffer, &keySize) == errSecSuccess else { return nil }
return Data(bytes: keyBuffer, count: keySize).base64EncodedString()
}
send RSA public key to iphone and use it to encrypt
This should do what you're asking - it encrypts data with the server's public key. It's not subject to MITM attacks, unless the attacker has a copy of your private key and its password (communicating via non-SSL, however, still is, but the data you encrypt with the server's legit public key will be nearly impossible to decrypt).
I cobbled this together from Apple's docs, this site, the Apple developer forums and probably elsewhere. So thanks to everyone I cribbed code from! This code assumes several things:
You've already generated your RSA key pairs (I'm using a 4096-bit key and it seems speedy enough) and, using the private key, created a DER-encoded certificate called "cert.cer" that you put in your resource bundle of your app (obviously, you can also download the cert from your server, but then you're open to MITM attacks again). By default, OpenSSL generates a PEM encoded cert, so you have to convert it with "openssl x509 -in cert.pem -inform PEM -out cert.cer -outform DER". iOS will barf on PEM. The reason I use a cert is it's actually easier to work with, and is supported in iOS. Using just the public key isn't (though it can be done).
You've added Security.framework to your project and you #import <Security/Security.h>.
/*
Returns an NSData of the encrypted text, or nil if encryption was unsuccessful.
Takes the X.509 certificate as NSData (from dataWithContentsOfFile:, for example)
*/
+(NSData *)encryptString:(NSString *)plainText withX509Certificate:(NSData *)certificate {
SecCertificateRef cert = SecCertificateCreateWithData(kCFAllocatorDefault, (__bridge CFDataRef)certificate);
SecPolicyRef policy = SecPolicyCreateBasicX509();
SecTrustRef trust;
OSStatus status = SecTrustCreateWithCertificates(cert, policy, &trust);
SecTrustResultType trustResult;
if (status == noErr) {
status = SecTrustEvaluate(trust, &trustResult);
}
SecKeyRef publicKey = SecTrustCopyPublicKey(trust);
const char *plain_text = [plainText UTF8String];
size_t blockSize = SecKeyGetBlockSize(publicKey);
NSMutableData *collectedCipherData = [NSMutableData data];
BOOL success = YES;
size_t cipherBufferSize = blockSize;
uint8_t *cipherBuffer = malloc(blockSize);
int i;
for (i = 0; i < strlen(plain_text); i += blockSize-11) {
int j;
for (j = 0; j < blockSize-11 && plain_text[i+j] != '\0'; ++j) {
cipherBuffer[j] = plain_text[i+j];
}
int result;
if ((result = SecKeyEncrypt(publicKey, kSecPaddingPKCS1, cipherBuffer, j, cipherBuffer, &cipherBufferSize)) == errSecSuccess) {
[collectedCipherData appendBytes:cipherBuffer length:cipherBufferSize];
} else {
success = NO;
break;
}
}
/* Free the Security Framework Five! */
CFRelease(cert);
CFRelease(policy);
CFRelease(trust);
CFRelease(publicKey);
free(cipherBuffer);
if (!success) {
return nil;
}
return [NSData dataWithData:collectedCipherData];
}
Encrypt using RSA Certificate in Swift
The code provided in question doesn't extract the Key from certificate. Rather, it tries to create the SecKey
using the certificate string itself. The correct way to do the same is to create a SecCertificate
object from the certificate data, then create a SecTrust
using the certificate data. Then using the trust, copy the public key to make SecKey
object.
The final code will look something like this:
import Foundation
import Security
struct RSA {
static func encrypt(string: String, certificate: String?) -> String? {
guard let certificate = certificate else { return nil }
let certificateString = certificate.replacingOccurrences(of: "-----BEGIN CERTIFICATE-----", with: "").replacingOccurrences(of: "-----END CERTIFICATE-----", with: "").replacingOccurrences(of: "\r", with: "").replacingOccurrences(of: "\n", with: "").replacingOccurrences(of: "\t", with: "").replacingOccurrences(of: " ", with: "")
print(certificateString)
// Convert the certificate string to Data
guard let data = Data(base64Encoded: certificateString) else { return nil }
print(data)
// Create SecCertificate object using certificate data
guard let cer = SecCertificateCreateWithData(nil, data as NSData) else { return nil }
var trust: SecTrust?
// Retrieve a SecTrust using the SecCertificate object. Provide X509 as policy
let status = SecTrustCreateWithCertificates(cer, SecPolicyCreateBasicX509(), &trust)
// Check if the trust generation is success
guard status == errSecSuccess else { return nil }
// Retrieve the SecKey using the trust hence generated
guard let secKey = SecTrustCopyPublicKey(trust!) else { return nil }
return encrypt(string: string, publicKey: secKey)
}
static func encrypt(string: String, publicKey: SecKey) -> String? {
let buffer = [UInt8](string.utf8)
var keySize = SecKeyGetBlockSize(publicKey)
var keyBuffer = [UInt8](repeating: 0, count: keySize)
// Encrypto should less than key length
guard SecKeyEncrypt(publicKey, SecPadding.PKCS1, buffer, buffer.count, &keyBuffer, &keySize) == errSecSuccess else { return nil }
return Data(bytes: keyBuffer, count: keySize).base64EncodedString()
}
}
var pemString = "-----BEGIN CERTIFICATE-----##Base 64 encoded certificate string##-----END CERTIFICATE-----"
let password = "abcde"
let encryptedPassword = RSA.encrypt(string: password, certificate: pemString)
print(encryptedPassword as Any)
The only change is in the static func encrypt(string: String, certificate: String?) -> String?
function.
Using an RSA public key on iOS
I found the necessary code on the Apple Site describing how to strip the ASN.1 header from the Public Key and load it into the KeyChain.
How I using an RSA public key generated and how I encrypted in iOS
this question might help you
RSA implementation's in Objective C
(IOS) RSA Encrypt/Decrypt AES Key
Related Topics
Detect Tap on Calloutbubble in Mkannotationview
Using Apple's Reachability Class in Swift
Module 'Alamofire' Has No Member Named 'Request'
How to Access iOS Private APIs in Swift
How to Customize Uirefreshcontrol with Different Image and Position
Swiftui in iOS14 Keyboard Avoidance Issues and Ignoressafearea Modifier Issues
How to Get Audio Controls on Lock Screen/Control Center from Avaudioplayer in Swift
Invalid Redeclaration in Auto Code Generate Nsmanagedobject Subclass Swift 3
Change Uifont in Secure Uitextfield Strange Behaviour in iOS7
Nsuserdefaultsdidchangenotification and Today Extensions
Change the Listing Order of the View Controllers in Xcode Storyboard
Uilocalnotification Isn't Working at All
Using Multiple Storyboards with a Tabbarcontroller
iOS Server Side Validation - Receipt Types