i am very tensed last 2 days due to encryption / decryption in triple Des in swift i am follow below link but not its show error where i get libraries of CCAlgorithem and CCOptions please check below image and please help me this
Note: I'm New In Swift Xcode
how to add these library in my code i'm new in swift
import UIKit
import CryptoSwift
class CypherSwift: NSObject {
func tripleDesEncrypt(pass: String) -> String{
//help from this thread
//http://stackoverflow.com/questions/25754147/issue-using-cccrypt-commoncrypt-in-swift
let keyString = "25d1d4cb0a08403e2acbcbe0"
let keyData: NSData! = (keyString as NSString).dataUsingEncoding(NSUTF8StringEncoding) as NSData!
let message = pass
let data: NSData! = (message as NSString).dataUsingEncoding(NSUTF8StringEncoding) as NSData!
let cryptData = NSMutableData(length: Int(data.length) + kCCBlockSize3DES)!
let keyLength = size_t(kCCKeySize3DES)
let operation: CCOperation = UInt32(kCCEncrypt)
let algoritm: CCAlgorithm = UInt32(kCCAlgorithm3DES)
let options: CCOptions = UInt32(kCCOptionECBMode + kCCOptionPKCS7Padding)
var numBytesEncrypted :size_t = 0
let cryptStatus = CCCrypt(operation,
algoritm,
options,
keyData.bytes, keyLength,
nil,
data.bytes, data.length,
cryptData.mutableBytes, cryptData.length,
&numBytesEncrypted)
if UInt32(cryptStatus) == UInt32(kCCSuccess) {
cryptData.length = Int(numBytesEncrypted)
// Not all data is a UTF-8 string so Base64 is used
var base64cryptString = cryptData.base64EncodedStringWithOptions(.Encoding64CharacterLineLength)
print("base64cryptString = \(base64cryptString)")
base64cryptString = base64cryptString + "\n"
return encodeString(base64cryptString)
} else {
print("Error: \(cryptStatus)")
}
return ""
}
func encodeString(str: String) -> String{
let customAllowedSet = NSCharacterSet(charactersInString:"==\n").invertedSet
let escapedString = str.stringByAddingPercentEncodingWithAllowedCharacters(customAllowedSet)
print("escapedString: \(escapedString)")
return escapedString!
}
}
image of error
tiple des link 1
triple des link 2
Unfortunately, there's currently no pre-defined Swift module for CommonCrypto, which means that you'll either have to create one yourself in a module.modulemap file, or import it in your bridging header. If you're making an app and not a framework, the latter is the easiest: just create a bridging header (if you don't have one, just add an Objective-C source file to the project and it'll offer to create one automatically; you can delete the Objective-C source file afterwards). Next, add this to the bridging header:
#import <CommonCrypto/CommonCrypto.h>
Note that if you're making a framework, the bridging header won't work and you'll have to make a modulemap instead (let me know if this is the case, and I'll edit something into the answer).
Anyway, the above will get rid of all the errors about kCC things not being found. Now that that's done, there are still a few things in the code that need fixing.
First of all, get rid of the unnecessary use of NS classes. Change:
let keyData: NSData! = (keyString as NSString).dataUsingEncoding(NSUTF8StringEncoding) as NSData!
to:
let keyData = keyString.data(using: .utf8)!
The ! is acceptable in this case, since we know what keyString is and we know that it's definitely always convertible to UTF-8.
Now, do the same thing for data. Unfortunately in this case, message depends on user input, so we shouldn't use !—if the message turns out not to be convertible to UTF-8, ! will cause your app to crash, which usually isn't what you want. It's better to use guard let and then bail if the conversion fails, either by making your function's return value optional and returning nil or adding throws to your function's return value and throwing an error:
guard let data = message.data(using: .utf8) else {
return nil
OR:
throw CocoaError(.fileReadInapplicableStringEncoding) // or some custom error
}
The next issue is the use of bytes on your Data object. In Swift, this is not allowed, because it's unsafe; if the Data is deallocated before you're done with bytes, you'll crash or run into other weird behavior. Instead, you should use withUnsafeBytes, and do the work requiring the bytes inside a closure. This is safer, since the Data is guaranteed to be valid at least until the closure returns. Since we have three separate Datas that we need the bytes of, this is kind of unwieldy with a triple-nested closure, but we can do it:
let cryptStatus = keyData.withUnsafeBytes { (keyBytes: UnsafePointer<UInt8>) in
data.withUnsafeBytes { (dataBytes: UnsafePointer<UInt8>) in
cryptData.withUnsafeMutableBytes { (cryptBytes: UnsafeMutablePointer<UInt8>) in
CCCrypt(operation,
algoritm,
options,
keyBytes,
keyLength,
nil,
dataBytes,
data.count,
cryptBytes,
cryptData.count,
&numBytesEncrypted)
}
}
}
After that, you've just got some more Objective-C-isms to make properly Swifty, and your encrypt function should be done:
cryptData.count = Int(numBytesEncrypted)
// Not all data is a UTF-8 string so Base64 is used
var base64cryptString = cryptData.base64EncodedString(options: .lineLength64Characters)
The only problem I see in the encode function is a few Objective-C-isms that you should modernize:
let customAllowedSet = CharacterSet(charactersIn: "==\n").inverted
let escapedString = str.addingPercentEncoding(withAllowedCharacters: customAllowedSet)
There's also the calling convention of your encode function; func encodeString(str: String) means you'll have to call it like return encodeString(str: base64cryptString) with the label present. If you want to call it without the label, you can change the signature to func encodeString(_ str: String).
Related
I receive some data from internet and need to guess the encoding if it's not provided, so I use this function stringEncoding(for:encodingOptions:convertedString:usedLossyConversion:), and it requires passing AutoreleasingUnsafeMutablePointer for receiving the converted string, I wrote code like this:
var str = "Hello, playground"
func decode(data: Data) -> String? {
var covertedString = NSString()
let stringPointer = AutoreleasingUnsafeMutablePointer<NSString?>(&covertedString)
guard NSString.stringEncoding(for: data, encodingOptions: nil, convertedString: stringPointer, usedLossyConversion: nil) != 0 else {
return nil
}
return covertedString as String
}
let data = str.data(using: .utf8)!
decode(data: data)
While the covertedString I got out of the function call is correct, the app always crashes. Any idea why AutoreleasingUnsafeMutablePointer is make it crashes? I tried to not passing convertedString, then it's not crashing any more, so looks like it's the root case. Any idea why it's crashing?
I am using Xcode Version 10.1 (10B61), with Swift 4
In your particular case the problem is that you have created an NSString, but then taken a pointer to a NSString?, which is a different thing.
But that doesn't really matter here. You don't create AutoreleasingUnsafeMutablePointer directly (or generally any kind of UnsafePointer). They're not promised to be valid by the time you use them. Instead, you create them implicitly using &.
func decode(data: Data) -> String? {
var convertedString: NSString? = "" // <- Make sure to make this optional
guard NSString.stringEncoding(for: data,
encodingOptions: nil,
convertedString: &convertedString, // <- Use &
usedLossyConversion: nil) != 0
else {
return nil
}
return convertedString as String?
}
I am looking at the docs for
CFStringGetCString
and AXUIElementCopyAttributeValue.
CFStringGetCString takes the param buffer: UnsafeMutablePointer<Int8>!
AXUIElementCopyAttributeValue takes the param value: UnsafeMutablePointer<CFTypeRef?>
For the latter, I can do a call like this:
var value: CFTypeRef?
let err = AXUIElementCopyAttributeValue(element, attribute as CFString, &value);
This satisfies the doc asking for an UnsafeMutablePointer of type CFTypeRef.
However I can't get the same logic to apply by doing
let buffer: Int8!
CFStringGetCString(attribute as! CFString, &buffer, 2048, CFStringBuiltInEncodings.UTF8.rawValue)
I also tried
let buffer: Int8?
CFStringGetCString(attribute as! CFString, &buffer!, 2048, CFStringBuiltInEncodings.UTF8.rawValue)
Either way, it complains about using buffer before it's initialized, even though it never complained about value in the working method with similar param requirements.
All the working examples I've seen for CFStringGetCString are using objective-c like syntax with *. Not sure what the proper swift way is here.
I also tried this way to get the value I wanted:
let app = AXUIElementCreateSystemWide();
var valueString = "";
var value: CFTypeRef?
// An exception on execution happens here when passing app
// Passing in the element I clicked instead of app
// yields error -25205 (attributeunsupported)
let err = AXUIElementCopyAttributeValue(app, "AXFocusedApplication" as CFString, &value);
if (err == AXError.success) {
valueString = value! as! NSString as String;
} else {
print("ERROR!");
print(err.rawValue);
}
return valueString;
Why are you torturing yourself with CFStringGetCString? If you have a CFString in Swift, you can cast it to a String and get a C string from that:
let cString: [Int8] = (cfString as String).cString(using: .utf8)!
Note also that the value of the kAXFocusedApplicationAttribute is not a CFString. It is an AXUIElement.
Here's my playground test:
import Foundation
import CoreFoundation
let axSystem = AXUIElementCreateSystemWide()
var cfValue: CFTypeRef?
AXUIElementCopyAttributeValue(axSystem, kAXFocusedApplicationAttribute as CFString, &cfValue)
if let cfValue = cfValue, CFGetTypeID(cfValue) == AXUIElementGetTypeID() {
let axFocusedApplication = cfValue
print(axFocusedApplication)
}
The first time I executed this playground, I got a system dialog box telling me that I need to give Xcode permission to control my computer. I went to System Preferences > Security & Privacy > Privacy > Accessibility, found Xcode at the bottom of the list, and turned on its checkbox.
Here's the output of the playground:
<AXUIElement Application 0x7fb2d60001c0> {pid=30253}
I assume you're on macOS since the AXUI API is only available on macOS. If you just want the name of the front application as a string, you can do this:
if let frontAppName = NSWorkspace.shared.frontmostApplication?.localizedName {
print(frontAppName)
}
I have been trying to implement encryption using CommonCrypto library in swift 4.2. But no luck, ending up with some unknown error.
Somebody please look at this code and help me.
func encrypty(data value: String) -> EncryptionResult {
guard var messageData = value.data(using: .utf8), var key = getSecretkey()?.data(using: .utf8) else {
return EncryptionResult.failure
}
//iv ata
guard let ivData = generateRandomBytes(of: Int32(SecurityConstants.blockSize))?.data(using: .utf8) else {
return EncryptionResult.failure
}
//output
var outputData = Data(count: (messageData.count + SecurityConstants.blockSize + ivData.count))
var localOutput = outputData
//output length
var outputLength: size_t = 0
//encyrption
let status = key.withUnsafeBytes { keyBytes in
messageData.withUnsafeBytes { messageBytes in
localOutput.withUnsafeMutableBytes { mutableOutput in
ivData.withUnsafeBytes { ivDataBytes in
CCCrypt( CCOperation(kCCEncrypt),
CCAlgorithm(kCCAlgorithmAES128),
CCOptions(kCCOptionPKCS7Padding),
keyBytes,
key.count,
ivDataBytes,
messageBytes,
messageData.count,
mutableOutput,
outputData.count,
&outputLength)
}
}
}
}
guard status == Int32(kCCSuccess) else {
logError("Error in encryption")
return EncryptionResult.failure
}
outputData.count = outputLength
return EncryptionResult.success(value: outputData.base64EncodedString())
}
Error -4310 is kCCKeySizeError (see CommonCryptoError.h). That means your key is not the right size.
Looking at this code, this in particular is very suspicious:
getSecretkey()?.data(using: .utf8)
If a key is decodable as UTF-8, it's not a proper key. You seem to have the same problem with your IV. I suspect that generateRandomBytes() does not quite do what it says it does. It's also not going to be possible to decrypt this data because you throw away the random IV (which the decryptor will require). You create room for it in the output (which is good), but you never write it.
I'm working on a little project and I came across this error which I can't find on the Internet.
This is my code:
let bufferRecieved = String(bytesNoCopy: buffer, length: length, encoding: .utf8, freeWhenDone: true)
guard let delimiterFirstIndex = bufferRecieved?.index(of: ":")!,
let name = bufferRecieved![..<delimiterFirstIndex],
let message = bufferRecieved![delimiterFirstIndex...] else {
return nil
}
I get:
Initializer for conditional binding must have Optional type, not 'String.SubSequence' (aka 'Substring') for the two instructions
let name = bufferRecieved![..<delimiterFirstIndex],
let message = bufferRecieved![delimiterFirstIndex...]
What does this error mean and how can I fix it?
name and message aren't Optionals, so there's no need for them to be part of the conditional binding. Just put them after the guard statement:
guard let bufferRecieved = String(bytesNoCopy: buffer, length: length, encoding: .utf8, freeWhenDone: true),
let delimiterFirstIndex = bufferRecieved.index(of: ":") else {
return nil
}
let name = bufferRecieved[..<delimiterFirstIndex]
let message = bufferRecieved[delimiterFirstIndex...]
use(name, message)
I'm trying to use key pair encryption to validate identity between my app and my PHP server. To do this I need to send the public key over to the server after I generate it in my app.
if let pubKey = NSData(base64EncodedData: publicKey, options: NSDataBase64DecodingOptions.allZeros)! {
println(pubKey)
}
publicKey is of type Unmanaged<SecKey>.
The error I'm getting in the above code is: Extra argument 'base64EncodedData' in call
How would I do this? Is there a better way?
Edit: This is how the keypair is generated:
var publicKeyPtr, privateKeyPtr: Unmanaged<SecKey>?
let parameters = [
String(kSecAttrKeyType): kSecAttrKeyTypeRSA,
String(kSecAttrKeySizeInBits): 2048
]
let result = SecKeyGeneratePair(parameters, &publicKeyPtr, &privateKeyPtr)
let publicKey = publicKeyPtr!.takeRetainedValue()
let privateKey = privateKeyPtr!.takeRetainedValue()
let blockSize = SecKeyGetBlockSize(publicKey)
Edit 2: So the issue is that SecKey is not NSData, so my question here should be: How do I convert a publicKey:SecKey to NSData?
It seems that you can temporary store the key to keychain and then get it back and convert it to data:
func convertSecKeyToBase64(inputKey: SecKey) ->String? {
// First Temp add to keychain
let tempTag = "de.a-bundle-id.temp"
let addParameters :[String:AnyObject] = [
String(kSecClass): kSecClassKey,
String(kSecAttrApplicationTag): tempTag,
String(kSecAttrKeyType): kSecAttrKeyTypeRSA,
String(kSecValueRef): inputKey,
String(kSecReturnData):kCFBooleanTrue
]
var keyPtr: Unmanaged<AnyObject>?
let result = SecItemAdd(addParameters, &keyPtr)
switch result {
case noErr:
let data = keyPtr!.takeRetainedValue() as! NSData
// Remove from Keychain again:
SecItemDelete(addParameters)
let encodingParameter = NSDataBase64EncodingOptions(rawValue: 0)
return data.base64EncodedStringWithOptions(encodingParameter)
case errSecDuplicateItem:
println("Duplicate Item")
SecItemDelete(addParameters)
return nil
case errSecItemNotFound:
println("Not found!")
return nil
default:
println("Error: \(result)")
return nil
}
}
While the fact is barely documented, you can pull out everything you need (that is, modulus and exponent) from the SecKey using SecKeyCopyAttributes.
See here for the details.
Swift 4 method to get base64 string from SecKey, publicKey :)
guard let publicKeyData = SecKeyCopyExternalRepresentation(publicKey!, nil) else {
NSLog("\tError obtaining export of public key.")
return ""
}
let publicKeyNSData = NSData(data: publicKeyData as Data)
let publicKeyBase64Str = publicKeyNSData.base64EncodedString()