When i convert the NSString to NSData and back i get a nil result
NSString * test = #"Wft0r3qkzXd5TDBeCahUB3MtHuc8Axwr";
NSData * testData = [test dataUsingEncoding:NSUTF8StringEncoding];
NSString * result = [NSString stringWithUTF8String:[testData bytes]];
Out
Printing description of testData:
<57667430 7233716b 7a586435 54444265 43616855 42334d74 48756338 41787772>
Printing description of result:
<nil>
I believe you're looking for this method:
- (instancetype)initWithData:(NSData *)data
encoding:(NSStringEncoding)encoding
From the apple doc's here: NSString class reference
In Swift, you can see the round-trip from string to data to string as follows:
let srcString = "Wft0r3qkzXd5TDBeCahUB3MtHuc8Axwr"
let stringAsData = srcString.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)!
let dstString = NSString(data: stringAsData, encoding: NSUTF8StringEncoding)!
dstString // => "Wft0r3qkzXd5TDBeCahUB3MtHuc8Axwr"
Basically, you want to use NSString(data:NSData,encoding:UInt) not NSString(UTF8String:UnsafePointer<Int8>).
An NSData is a Cocoa object that wraps a buffer of bytes. But the method you were using takes an UnsafePointer<Int8>, in other words, a raw pointer, which is just a numerical memory address pointing to the start of an array of bytes.
Swift 3
let string = "aHft0r3qkzjuh5rdsaeCahUB3MtHuc8Axwrfdvxgf"
let stringData = string.data(using: String.Encoding.utf8, allowLossyConversion: false)!
let finalString = NSString(data: stringData, encoding: String.Encoding.utf8.rawValue)!;
So I'm trying to convert some obj-c code into swift but I'm stuck on a part of it.
How can I do something like this in swift?
- (void)sometMethod:(NSString *)s {
NSString * crlfString = [s stringByAppendingString:#"\r\n"];
uint8_t *buf = (uint8_t *)[crlfString UTF8String];}
The real problem is this line
uint8_t *buf = (uint8_t *)[crlfString UTF8String];
What do you want to do with the UTF-8 buffer? Generally, it is more convenient to convert the string directly to an NSData object. But you can also translate your Obj-C code one by one to Swift. Here are both variants:
import Foundation
func appendCRLFAndConvertToUTF8_1(s: String) -> NSData {
let crlfString: NSString = s.stringByAppendingString("\r\n")
let buffer = crlfString.UTF8String
let bufferLength = crlfString.lengthOfBytesUsingEncoding(NSUTF8StringEncoding)
let data = NSData(bytes: buffer, length: bufferLength)
return data;
}
func appendCRLFAndConvertToUTF8_2(s: String) -> NSData {
let crlfString = s + "\r\n"
return crlfString.dataUsingEncoding(NSUTF8StringEncoding)!
}
let s = "Hello 😄"
let data1 = appendCRLFAndConvertToUTF8_1(s)
data1.description
let data2 = appendCRLFAndConvertToUTF8_2(s)
data2.description
data1 == data2
And if you want to iterate over the UTF-8 code units and not deal with a buffer, use something like:
for codeUnit in String.utf8 {
println(codeUnit)
}
I'm having communcation issues between my app and the server. I'm using RNCryptor to encrypt a message, which I then base64 encode and transfer to the server in the request. This is done in both the DATA header, and within the http body as post data. I think I'm making a mistake in how I'm converting & transferring the base64 encoded message via POST.
If I receive the encrypted message via the header, it decrypts perfectly fine, every single time. However, if I take the message via the POST data, I'm getting varying results. Most of the time, it fails, else it partially decrypts (first few letters), with 1 in 20 or so successful decryptions.
The objective-c code is:
- (NSString *)sendEncryptedTestMessage:(NSString *)address{
NSString* messageContent = #"Hello my name is Bob.";
NSError * error = nil;
NSString* responseString2 = nil;
NSData* postData = [RNEncryptor encryptData:[messageContent dataUsingEncoding:NSUTF8StringEncoding]
withSettings:kRNCryptorAES256Settings
password:#"123456"
error:&error];
NSString* messageServer = [NSString base64forData:postData];
NSString* postMessage = [#"message=" stringByAppendingString:messageServer];
postData = [postMessage dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES]; // problem here I think
NSString* postLength = [NSString stringWithFormat:#"%ld",(unsigned long)[postData length]];
NSURL* URLToRequest = [NSURL URLWithString:address];
NSMutableURLRequest* semisystem = [[[NSMutableURLRequest alloc] initWithURL:URLToRequest] autorelease];
[semisystem setHTTPMethod:#"POST"];
[semisystem setHTTPBody:postData];
[semisystem setValue:postLength forHTTPHeaderField:#"Content-Length"];
[semisystem setValue:self.activationURL forHTTPHeaderField:#"EncryptionKey"];
[semisystem setValue:messageServer forHTTPHeaderField:#"data"];
NSURLResponse* response;
NSData* data = [NSURLConnection sendSynchronousRequest:semisystem
returningResponse:&response
error:&error];
responseString2 = [NSString stringWithFormat:#"%.*s", (int)[data length], [data bytes]];
return responseString2;
}
PHP code:
function decrypt2($b64_data,$password)
{
// back to binary
//$bin_data = mb_convert_encoding($b64_data, "UTF-8", "BASE64");
$bin_data = base64_decode($b64_data);
// extract salt
$salt = substr($bin_data, 2, 8);
// extract HMAC salt
$hmac_salt = substr($bin_data, 10, 8);
// extract IV
$iv = substr($bin_data, 18, 16);
// extract data
$data = substr($bin_data, 34, strlen($bin_data) - 34 - 32);
$dataWithoutHMAC = chr(2).chr(1).$salt.$hmac_salt.$iv.$data;
// extract HMAC
$hmac = substr($bin_data, strlen($bin_data) - 32);
// make HMAC key
$hmac_key = pbkdf2('SHA1', $password, $hmac_salt, 10000, 32, true);
// make HMAC hash
$hmac_hash = hash_hmac('sha256', $dataWithoutHMAC , $hmac_key, true);
// check if HMAC hash matches HMAC
if($hmac_hash != $hmac) {
echo "HMAC mismatch".$nl.$nl.$nl;
// return false;
}
// make data key
$key = pbkdf2('SHA1', $password, $salt, 10000, 32, true);
// decrypt
$ret = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $data, MCRYPT_MODE_CBC, $iv);
return $ret;
}
$passkey = "123456";
$messageBase64 = $_POST['message'];// THIS barely works
$messageBase64 = $_SERVER['HTTP_DATA'];// THIS WORKS
$message = decrypt2($messageBase64,$passkey);
Many thanks in advance!
I know this is a old question, but for a long time I used the same solution and the problem was that we are not encoding properly the url before making the request to the server. The documentation says:
According to RFC 3986, the reserved characters in a URL are:
reserved = gen-delims / sub-delims
gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "#"
sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
/ "*" / "+" / "," / ";" / "="
And here is how to encode the string:/
CFStringRef encodedString =
CFURLCreateStringByAddingPercentEscapes(
kCFAllocatorDefault,
(__bridge CFStringRef)(originalString),
NULL,
CFSTR(":/?#[]#!$&'()*+,;="),kCFStringEncodingUTF8);
And to get the string again:
NSString* stringEncoded = CFBridgingRelease
(CFURLCreateWithString(kCFAllocatorDefault, encodedString, NULL));
I think this is the best we can do, because we make sure that string will be properly encoded and during the request the symbols will not be replaced for other thing.
here is the references:
http://developer.apple.com/library/ios/#documentation/CoreFoundation/Reference/CFURLRef/Reference/reference.html#//apple_ref/c/func/CFURLCreateStringByAddingPercentEscapes
http://developer.apple.com/library/ios/#documentation/NetworkingInternetWeb/Conceptual/NetworkingOverview/WorkingWithHTTPAndHTTPSRequests/WorkingWithHTTPAndHTTPSRequests.html
I've just found the solution. During the request, the '+' symbols are being interpreted as whitespaces by the server, breaking the base64 code. The following line fixed this problem:
postMessage = [postMessage stringByReplacingOccurrencesOfString:#"+" withString:#"%2B"];
you can check your encoded/decoded string, in this url
http://meyerweb.com/eric/tools/dencoder/
As you can see "+" change by "%2B" when you press encode button.
I have a static method defined as follows:
+(NSString*)getNewIdAsBase64
{
// Grab new uuid
CFUUIDRef originalUuid = CFUUIDCreate(nil);//create a new UUID
//NSLog(#"Step a: original uuidObj = %#",originalUuid);
CFUUIDBytes originalBytes = CFUUIDGetUUIDBytes (originalUuid);//ISSUE
NSData* data88 = [NSData dataWithBytes: &originalBytes length: sizeof(originalBytes)];
NSString* hugo = [data88 base64EncodedString];
return hugo;
}
When I run Product->Analyze on my project then the line commented with //ISSUE raises the following issue:
Potential leak of an object alocated on line 23 and stored into 'originalUuid'
What am I doing wrong, and how do I fix it?
Thanks
You will need to release the object you create even if you are using ARC:
+(NSString*)getNewIdAsBase64
{
// Grab new uuid
CFUUIDRef originalUuid = CFUUIDCreate(nil);//create a new UUID
//NSLog(#"Step a: original uuidObj = %#",originalUuid);
CFUUIDBytes originalBytes = CFUUIDGetUUIDBytes (originalUuid);//ISSUE
NSData* data88 = [NSData dataWithBytes: &originalBytes length: sizeof(originalBytes)];
NSString* hugo = [data88 base64EncodedString];
CFRelease(originalUuid);
return hugo;
}
as I'm only a beginner in this field this question may seem to be very trivial, but I beg your pardon. I've a Java code as follows:
String passwordSalt = "somesalt";
byte[] bsalt = base64ToByte(passwordSalt);
byte[] thePasswordToDigestAsBytes = ("somepassword").getBytes("UTF-8");
System.out.println("------------------------------"+passwordSalt);
MessageDigest digest = MessageDigest.getInstance("SHA-512");
digest.reset();
digest.update(bsalt);
byte[] input = digest.digest(thePasswordToDigestAsBytes);
System.out.println("------------------------------"+byteToBase64(input));
I want to achieve the same in Objective-C and I'm using the following code :
NSData *saltdata = [Base64 decode:#"some base64 encoded salt"];
NSString *passwordDgst;
passwordDgst = #"somepassword";
NSData *input = [passwordDgst dataUsingEncoding: NSUTF8StringEncoding];
unsigned char hash[CC_SHA512_DIGEST_LENGTH];
CC_SHA512_CTX context;
CC_SHA512_Init(&context);
CC_SHA512_Update(&context, [saltdata bytes], (CC_LONG)[saltdata length]);
CC_SHA512_Update(&context, [input bytes], (CC_LONG)[input length]);
CC_SHA512_Final(hash, &context);
input = [NSMutableData dataWithBytes:(const void *)hash length:sizeof(unsigned char)*CC_SHA512_DIGEST_LENGTH];
passwordDgst = [input encodeBase64WithNewlines:NO];
But this seems to generate a different hash than the Java Code? Why is that? Can anybody clarify me that? Thanks in advance :)