How could I send hashed password with sha256 via post request ?
func sha256(string: String) -> Data? {
guard let messageData = string.data(using:String.Encoding.utf8) else { return nil; }
var digestData = Data(count: Int(CC_SHA256_DIGEST_LENGTH))
_ = digestData.withUnsafeMutableBytes {digestBytes in
messageData.withUnsafeBytes {messageBytes in
CC_SHA256(messageBytes, CC_LONG(messageData.count), digestBytes)
}
}
return digestData
}
This is how I am hasing a password.
Then whenever I try to pack it into an array as a [String: Any] it throws an exception in JSONSErialization 'NSInvalidArgumentException', reason: 'Invalid type in JSON write (Foundation._SwiftNSData)'
guard let loginURL = URL(string: LOGIN_URL) else {
print("Error: cannot create URL")
return
}
var loginURLRequest = URLRequest(url: loginURL)
loginURLRequest.httpMethod = "POST"
let content: [String: Any] = ["username": username, "passwordHash": password]
let json: Data
do {
json = try JSONSerialization.data(withJSONObject: content, options: [])
loginURLRequest.httpBody = json
} catch {
print("Error: Can not create JSON")
return
}
Thanks in advance!
What you probably want to do is encode the hash as a hex string. Given your sha256 function defined above, The following will do that:
let password = sha256(string: "myPassword")
.map { return String(format: "%02x", $0) }
.joined()
let content = [
"username": username,
"passwordHash": password
]
Alternatively, you could change your sha256 function to return a string (and make it an extension of string):
func sha256() -> String? {
guard let messageData = data(using:String.Encoding.utf8) else {
return nil
}
var digestData = Data(count: Int(CC_SHA256_DIGEST_LENGTH))
_ = digestData.withUnsafeMutableBytes { digestBytes in
withUnsafeBytes { messageBytes in
CC_SHA256(messageBytes, CC_LONG(messageData.count), digestBytes)
}
}
return digestData.map { return String(format: "%02x", $0) }.joined()
}
Note: I'm winging this a little since CommonCrypto won't work in a playground and I'm too lazy to wrap a whole project around this, but the important parts are here.
Use data.map to iterate over each byte in the hash
convert it to a hex string with String(format: "%02x"...)
put it all back together with joined()
Related
I'm currently making app for Destiny 2 API.
and I'm struggling with this issue
this is my whole function code that makes hash data to item name
I want to return that name variable which is guarded last, but that completion handler
runs after function is end.
I searched to internet, but almost everyone just used this data inside of it, not
function return.
that I only need is " Parse json and get returned data I want "
is there any idea please?
item parameter means " item hash to get name of it "
lang parameter means " language to return " if this is "en" then, it should return English.
here's the data I pared too " https://pastebin.com/1tV6fx9F "
func hashToName(item: String, lang: String = "ko") (" want to return String "-> String ){
let url = String(format: "https://www.bungie.net/platform/Destiny2/Manifest/DestinyInventoryItemDefinition/\(item)")
let param: [String: String] = ["lc": "\(lang)"]
let head: HTTPHeaders = ["x-api-key": "b21e4d2d33234b82be6e56893554974b"]
let doNetwork = AF.request(url, method:.get, parameters: param, encoder: URLEncodedFormParameterEncoder.default, headers: head)
doNetwork.responseJSON {
response in
switch response.result {
case .success(let site):
guard let dict = site as? NSDictionary else { return }
guard let res = dict["Response"] as? NSDictionary else { return }
guard let prop = res["displayProperties"] as? NSDictionary else { return }
guard let name: String = prop["name"] as? String else { return }
print(name) // data I want to return
case .failure(let err):
print(err.localizedDescription)
}
}
}
func hashToName(item: String, lang: String = "ko", returnString: #escaping (String)->()) {
let url = String(format: "https://www.bungie.net/platform/Destiny2/Manifest/DestinyInventoryItemDefinition/\(item)")
let param: [String: String] = ["lc": "\(lang)"]
let head: HTTPHeaders = ["x-api-key": "b21e4d2d33234b82be6e56893554974b"]
let doNetwork = AF.request(url, method:.get, parameters: param, encoder: URLEncodedFormParameterEncoder.default, headers: head)
doNetwork.responseJSON {
response in
switch response.result {
case .success(let site):
guard let dict = site as? NSDictionary else { return }
guard let res = dict["Response"] as? NSDictionary else { return }
guard let prop = res["displayProperties"] as? NSDictionary else { return }
guard let name: String = prop["name"] as? String else { return }
returnString(name)
print(name) // data I want to return
case .failure(let err):
print(err.localizedDescription)
}
}
}
//How to use
hashToName(item: "Your string") { str in
print(str)
}
I'm making an Application with a java backend and a Swift front-end. Using a REST Api to move data. I wish to encrypt the data with AES 128 CBC. The encrypting method is working, but the decrypting method is not.
First off all, this is the Swift code for de AES encrypting and decrypting:
import Foundation
import CommonCrypto
struct AES {
private let key: Data
private let iv: Data
init?() {
let ivProduct: String = "dkghepfowntislqn"
let keyProduct: String = "2949382094230487"
guard keyProduct.count == kCCKeySizeAES128 || keyProduct.count == kCCKeySizeAES256, let keyData = keyProduct.data(using: .utf8) else {
debugPrint("Error: Failed to set a key.")
return nil
}
guard ivProduct.count == kCCBlockSizeAES128, let ivData = ivProduct.data(using: .utf8) else {
debugPrint("Error: Failed to set an initial vector.")
return nil
}
self.key = keyData
self.iv = ivData
}
func encrypt(string: String) -> Data? {
return crypt(data: string.data(using: .utf8), option: CCOperation(kCCEncrypt))
}
func decrypt(data: Data?) -> String? {
guard let decryptedData = crypt(data: data, option: CCOperation(kCCDecrypt)) else { return nil }
return String(bytes: decryptedData, encoding: .utf8)
}
func crypt(data: Data?, option: CCOperation) -> Data? {
guard let data = data else { return nil }
let cryptLength = data.count + kCCBlockSizeAES128
var cryptData = Data(count: cryptLength)
let keyLength = key.count
let options = CCOptions(kCCOptionPKCS7Padding)
var bytesLength = Int(0)
let status = cryptData.withUnsafeMutableBytes { cryptBytes in
data.withUnsafeBytes { dataBytes in
iv.withUnsafeBytes { ivBytes in
key.withUnsafeBytes { keyBytes in
CCCrypt(option, CCAlgorithm(kCCAlgorithmAES), options, keyBytes.baseAddress, keyLength, ivBytes.baseAddress, dataBytes.baseAddress, data.count, cryptBytes.baseAddress, cryptLength, &bytesLength)
}
}
}
}
guard UInt32(status) == UInt32(kCCSuccess) else {
debugPrint("Error: Failed to crypt data. Status \(status)")
return nil
}
cryptData.removeSubrange(bytesLength..<cryptData.count)
return cryptData
}
}
The data is gathered from the REST API like so:
func getTestAllPayments(_ completion: #escaping ([Payment]) -> ()) {
let aes128 = AES()
if let url = URL(string: "\(localhostUrl)/payment") {
URLSession.shared.dataTask(with: url) { data, response, error in
if let data = data {
do {
let res = try JSONDecoder().decode([Payment].self, from: (data))
print(res.self)
completion(res)
return
} catch let error {
print(error)
}
}
}.resume()
}
}
Now for the problem. I've ran a couple of test:
first check if the encrypt and decrypt methods work together:
let aes128 = AES()
let dataEncrypt = aes128?.encrypt(string:"Hello") //Will be :lG7Bqk0nwx732eOQLAzhqQ==
let dataDecrypt = aes128?.decrypt(data:dataEncrypt) //Will be: "Hello"
print(dataDecrypt) --> //output = "Hello"
First test works like a charm. For the second test:
let aes128 = AES()
if let url = URL(string: "\(localhostUrl)/payment") {
URLSession.shared.dataTask(with: url) { data, response, error in
if let data = data {
print(String(data: data, encoding: .utf8)) //Output = lG7Bqk0nwx732eOQLAzhqQ==
let dataDecrypt = aes128?.decrypt(data: data)
print(dataDecrypt) --> //output = nil
This is where it goes wrong. When fetching the data with the exact same encoding string, it'll always return nil. Has it something to do with the data format that URLSession returns?
I am trying to send a multipart/form-data request via URLSession I have written a helper function to create the form body as Data for me, however my request keeps failing with a 500 response code.
I was trying to print out the string representation of my request to ensure the body is correct, however simply trying to decode it now is throwing an error as The data couldn’t be read because it isn’t in the correct format.
This leads me to believe something is wrong with how my request is being encoded.
This is essentially my setup -
struct Media {
let key: String
let filename: String
let data: Data
let mimeType: String
init?(withImage image: UIImage, forKey key: String) {
self.key = key
self.mimeType = "image/jpeg"
self.filename = "avatar.jpg"
guard let data = image.jpegData(compressionQuality: 0.7) else { return nil }
self.data = data
}
}
typealias Parameters = [String: String]
func createFormData(usingParams params: Parameters?, media: [Media]?, boundary: String) -> Data {
let lineBreak = "\r\n"
var body = Data()
if let parameters = params {
for (key, value) in parameters {
body.append(string:"--\(boundary + lineBreak)")
body.append(string:"Content-Disposition: form-data; name=\"\(key)\"\(lineBreak + lineBreak)")
body.append(string:"\(value + lineBreak)")
}
}
if let media = media {
for photo in media {
body.append(string:"--\(boundary + lineBreak)")
body.append(string:"Content-Disposition: form-data; name=\"\(photo.key)\"; filename=\"\(photo.filename)\"\(lineBreak)")
body.append(string:"Content-Type: \(photo.mimeType + lineBreak + lineBreak)")
body.append(photo.data)
body.append(string: lineBreak)
}
}
body.append(string: "--\(boundary)--\(lineBreak)")
return body
}
extension Data {
mutating func append(string: String) {
if let data = string.data(using: .utf8) {
append(data)
}
}
}
Which I invoke something like this -
let boundary = UUID().uuidString
guard let profilePic = Media(withImage:image, forKey: "file") else { return }
let data = createFormData(usingParams: nil, media: [profilePic], boundary: boundary)
I have tried to print my data using the following -
do {
print(data)
let json = try JSONSerialization.jsonObject(with: data, options: []) as? [String : Any]
print(json)
} catch let error {
print(error.localizedDescription)
}
This throws the error mentioned earlier.
I have also tried
let string = String(data: data, encoding: .utf8)
print(string)
This however just returns nil.
I noticed if I remove body.append(photo.data) the data can print out now as JSON, however I am not sure why this matters
Need help with swift 3. I got
cannot convert value of type string to expected argument type string
func authKMA(text: String) {
let base = "http://api.kma1.biz/?method=auth"
let userlogin = "&username=vostok3r#gmail.com"
let userpass = "&pass=0000"
_ = ""
_ = ""
let auth = base + userlogin + userpass
let url = URL(string: auth)!
URLSession.shared.dataTask(with: url) { (data, _, _) in
guard let gotdata = data else {
print("Сервер не отвечает")
return
}
guard let jsonAny = try? JSONSerialization.jsonObject(with: gotdata, options: []) else {
print("Сервер не дал информацию по аккаунту")
return
}
guard let json = jsonAny as? [String: Any] else {
return
}
guard let authhasher = json.index(of: "authhash") else {
return
//ERROR: cannot convert value of type string to expected argument type string//
}
print(authhasher)
}.resume()
}
}
As Dávid Pásztor commented, Dictionary doesn't have index(of:) method. If all you're trying to do is extract the authhash value from your json dictionary, you can access your values using subscript notation:
guard let authhasher = json["authhash"] as? String else {
return
}
print(authhasher)
I am receiving a base64String from webservice response in NSData, how to convert that base64String to String in swift?
//Code
var jsonResult = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: &err) as! NSDictionary // Response JSON from webservice
var base64String : String = ""
base64String = jsonResult["Base64String"] as! String // Retrieve base64String as string from json response
println("Base64String Alone: \(base64String)")
// Code to decode that base64String
let decodedData = NSData(base64EncodedString: base64String, options: NSDataBase64DecodingOptions(rawValue: 0))
println("Decoded: \(decodedData)")
let decodedString = NSString(data: decodedData!, encoding: NSUTF8StringEncoding)
println(decodedString) // Prints nil
Encode and decode of base64String works well for the files containing only text, if a file contains some table formats/images both encoding and decoding gives an invalid base64String. How to convert a file into base64String encode and decode whatever the contents of file ?
File formats are doc, docx, pdf, txt
Advance thanks for any help !
Try this:
let base64Encoded = "YW55IGNhcm5hbCBwbGVhc3VyZS4="
var decodedString = ""
if let decodedData = Data(base64Encoded: base64Encoded) {
decodedString = String(data: decodedData, encoding: .utf8)!
}
if !decodedString.isEmpty {
print(decodedString)
} else {
print("Oops, invalid input format!")
}
Make sure your base 64 encoded string is valid.
WARNING (edit)
In most base64 decoding implementations like Java, the padding-character is not needed, but Data(base64Encoded:) returns nil if it's missing.
Swift 5 solution; use String.fromBase64(_:) instead, after implementing like:
extension Data {
/// Same as ``Data(base64Encoded:)``, but adds padding automatically
/// (if missing, instead of returning `nil`).
public static func fromBase64(_ encoded: String) -> Data? {
// Prefixes padding-character(s) (if needed).
var encoded = encoded;
let remainder = encoded.count % 4
if remainder > 0 {
encoded = encoded.padding(
toLength: encoded.count + 4 - remainder,
withPad: "=", startingAt: 0);
}
// Finally, decode.
return Data(base64Encoded: encoded);
}
}
extension String {
public static func fromBase64(_ encoded: String) -> String? {
if let data = Data.fromBase64(encoded) {
return String(data: data, encoding: .utf8)
}
return nil;
}
}
As mentioned on editor's profile,
above edit's code allows Apache 2.0 license as well,
without attribution need.
Swift extension is handy.
extension String {
func base64Encoded() -> String? {
return data(using: .utf8)?.base64EncodedString()
}
func base64Decoded() -> String? {
guard let data = Data(base64Encoded: self) else { return nil }
return String(data: data, encoding: .utf8)
}
}
"heroes".base64Encoded() // It will return: aGVyb2Vz
"aGVyb2Vz".base64Decoded() // It will return: heroes
i've made an update to Ashok Kumar S answer to add filler character when string size is not divisible by 4, raising an exception and returning nil
extension String {
func base64Encoded() -> String? {
return data(using: .utf8)?.base64EncodedString()
}
func base64Decoded() -> String? {
var st = self;
if (self.count % 4 <= 2){
st += String(repeating: "=", count: (self.count % 4))
}
guard let data = Data(base64Encoded: st) else { return nil }
return String(data: data, encoding: .utf8)
}
You can encrypt/decrypt base64 strings using this extension:
public extension String {
var base64Decoded: String? {
guard let decodedData = Data(base64Encoded: self) else { return nil }
return String(data: decodedData, encoding: .utf8)
}
var base64Encoded: String? {
let plainData = data(using: .utf8)
return plainData?.base64EncodedString()
}
}
To Encode:
"Hello World!".base64Encoded
Result is an Optional string: "SGVsbG8gV29ybGQh"
To Decode:
"SGVsbG8gV29ybGQh".base64Decoded
Result is an Optional string: "Hello World!"
Source
The above answers are core, but i had an error like
fatal error, found nil while unwrapping an optional value
The solution is adding options
extension String {
//: ### Base64 encoding a string
func base64Encoded() -> String? {
if let data = self.data(using: .utf8) {
return data.base64EncodedString()
}
return nil
}
//: ### Base64 decoding a string
func base64Decoded() -> String? {
if let data = Data(base64Encoded: self, options: .ignoreUnknownCharacters) {
return String(data: data, encoding: .utf8)
}
return nil
}
}
and use it safely
var str = "HelloWorld"
if let base64Str = str.base64Encoded() {
print("Base64 encoded string: \"\(base64Str)\"")
if let trs = base64Str.base64Decoded() {
print("Base64 decoded string: \"\(trs)\"")
}
}