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 :)
Related
I am trying to use c++ api with objc native code in flutter.
https://docs.flutter.dev/development/platform-integration/platform-channels?tab=type-mappings-obj-c-tab
flutter documentation says Uint8List should be stored as FlutterStandardTypedData typedDataWithBytes: in objc do
send argument in flutter
var data = <String, Uint8List>{
"key": byte, //data type is Uint8List
"value": byteBuffer, //data type is Uint8List
};
Uint8List? byteRes;
byteRes = await platform.invokeMethod('SeedDecrypt', data);
get argument in objc (AppDelegate.m)
NSData* key = call.arguments[#"key"];
NSData* value = call.arguments[#"value"];
NSUInteger keyLength = [key length];
NSUInteger valueLength = [value length];
Byte* byteKey = (Byte*)malloc(keyLength);
Byte* byteValue = (Byte*)malloc(valueLength);
memcpy(byteKey, [key bytes], keyLength);
memcpy(byteValue, [value bytes], byteLength);
DWORD roundKey[32];
//Call C++ API
//prototype : void SeedKey(DWORD* roundKey, BYTE* byteKey);
SeedKey(roundKey, byteKey);
//protoType : void Decrypt(BYTE* byteValue, DWORD* roundKey);
Decrypt(byteValue, roundKey);
NSData* res = [NSData dataWithBytes: byteValue length: sizeof(byteValue)];
result(res);
Store the argument as NSData* and copy the memory to a Byte* variable. After executing the C API, it is converted to NSData type. The problem is that when I run it, the device shuts down. I wrote this source referring to the article below. Do you know what my mistake is?
How to convert NSData to byte array in iPhone?
thanks.
Solved
NSNumber* keyLength = call.arguments[#"keyLen"];
NSNumber* valueLength = call.arguments[#"valueLen"];
NSUInteger keyLen = [keyLength integerValue];
NSUInteger valueLen = [valueLength integerValue];
FlutterStandardTypedData* key = call.arguments[#"key"];
FlutterStandardTypedData* value = call.arguments[#"value"];
Byte* byteKey = (Byte*)malloc(keyLen);
Byte* byteValye = (Byte*)malloc(valueLen);
memcpy(byteKey, [key.data bytes], keyLen);
memcpy(byteValue, [value.data bytes], valueLen);
DWORD roundKey[32];
//Call C++ API
NSData* res = [NSData dataWithBytes:keyValue length:keyLen];
FlutterStandardTypedData* rest = [FlutterStandardTypedData typedDataWithBytes: res];
free(byteKey);
free(byteValue);
result(rest);
See https://docs.flutter.dev/development/platform-integration/platform-channels?tab=type-mappings-obj-c-tab. After matching the data type, match the OBJC data type with the C data type and return the result.
var index=2;
var validFor="CAAA";
function isDependentValue(index, validFor)
{
var base64 = new sforce.Base64Binary("");
var decoded = base64.decode(validFor);
var bits = decoded.charCodeAt(index>>3);
return ((bits & (0x80 >> (index%8))) != 0);
}
The above code is written in Javascript.I have to do the same in my iOS app.How can i do it with Objective-c.I have decoded the validFor string by using of this POST
Need help on this
If you are looking to convert a string to base64, the code below shows a brief example:
NSData *nsdata = [#"String to encode"
dataUsingEncoding:NSUTF8StringEncoding];
// Get NSString from NSData object in Base64
NSString *base64Encoded = [nsdata base64EncodedStringWithOptions:0];
I am trying to create a 16 byte and later 32 byte initialization vector in objective-c (Mac OS). I took some code on how to create random bytes and modified it to 16 bytes, but I have some difficulty with this. The NSData dumps the hex, but an NSString dump gives nil, and a cstring NSLog gives the wrong number of characters (not reproduced the same in the dump here).
Here is my terminal output:
2012-01-07 14:29:07.705 Test3Test[4633:80f] iv hex <48ea262d efd8f5f5 f8021126 fd74c9fd>
2012-01-07 14:29:07.710 Test3Test[4633:80f] IV string: (null)
2012-01-07 14:29:07.711 Test3Test[4633:80f] IV char string t^Q¶�^��^A
Here is the main program:
int main (int argc, const char * argv[])
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
//NSString *iv_string = [NSString stringWithCString:iv encoding:NSUTF8StringEncoding];
testclass *obj = [testclass alloc];
NSData *iv_data = [obj createRandomNSData];
//[iv_string dataUsingEncoding:NSUTF8StringEncoding];
NSLog(#"iv hex %#",iv_data);
//NSString *iv_string = [[NSString alloc] initWithBytes:[iv_data bytes] length:16 encoding:NSUTF8StringE$
NSString *iv_string = [[NSString alloc] initWithData:iv_data encoding:NSUTF8StringEncoding];
NSLog(#"IV string: %#",iv_string);
NSLog(#"IV char string %.*s",[iv_data bytes]);
return 0;
]
(I left in the above some commented code that I tried and did not work also).
Below is my random number generater, taken from a stack overflow example:
#implementation testclass
-(NSData*)createRandomNSData
{
int twentyMb = 16;
NSMutableData* theData = [NSMutableData dataWithCapacity:twentyMb];
for( unsigned int i = 0 ; i < twentyMb/4 ; ++i )
{
u_int32_t randomBits = arc4random();
[theData appendBytes:(void*)&randomBits length:4];
}
NSData *data = [NSData dataWithData:theData];
[theData dealloc];
return data;
}
#end
I am really quite clueless as to what could be the problem here. If I have data as bytes, it should convert to a string or not necessarily? I have looked over the relevant examples here on stackoverflow, but none of them have worked in this situation.
Thanks,
Elijah
An arbitrary byte sequence may not be legal UTF8 encoding. As #Joachim Isaksson notes, there is seldom reason to convert to strings this way. If you need to store random data as a string, you should use an encoding scheme like Base64, serialize the NSData to a plist, or similar approach. You cannot simply use a cstring either, since NULL is legal inside of a random byte sequence, but is not legal inside of a cstring.
You do not need to build your own random byte creator on Mac or iOS. There's one built-in called SecRandomCopyBytes(). For example (from Properly encrypting with AES with CommonCrypto):
+ (NSData *)randomDataOfLength:(size_t)length {
NSMutableData *data = [NSMutableData dataWithLength:length];
int result = SecRandomCopyBytes(kSecRandomDefault,
length,
data.mutableBytes);
NSAssert(result == 0, #"Unable to generate random bytes: %d",
errno);
return data;
}
When converting NSData to NSString using an UTF8 encoding, you won't necessarily end up with the same number of bytes since not all binary values are valid encodings of characters. I'd say using a string for binary data is a recipe for problems.
What is the use of the string? NSData is exactly the datatype you want for storing binary data to begin with.
I need to work out a decryption/encryption algorithm, but I'm confused regarding SHA256 / CBC / Salt / IV etc.
An example of a correctly encrypted string is:
U2FsdGVkX19IfIZtJ/48wk8z3ZRGDK8RD8agyQRhMrsOMsoIlVEcrzraOLo5IRBXjDkN1JUFnNrkvi2NA22IOTv00U97065tUNBQKEVXcaL0UJirtcqHlq8lN4pEm14ZokKXv8mUP8GkUKrOf37GhOugi/F/CQiILb57kIPrYPk=
It is Base64 encoded then Rijndael encoded. The first 8 characters are 'Salted__' and the next 8 characters I assume is some sort of salt (randomly generated).
The key I provided to encrypt this data is '12345678'.
The decrypted data should be:
2358442189442905:ZGF2aWQ=:1324515293:1.9.12:1:MC4wLjAuMCxub25lLzA=:LfcTMMYyUcwgL8keu3sMoNC/PFEKZy8fWFvo3rJvSdo
Apparently it is following Crypt::CBC::VERSION 2.29
I can't seem to decrypt the correctly encrypted string above. I have tried the following:
NSString *key = #"12345678";
NSData *test = [NSData dataFromBase64String:#"U2FsdGVkX19IfIZtJ/48wk8z3ZRGDK8RD8agyQRhMrsOMsoIlVEcrzraOLo5IRBXjDkN1JUFnNrkvi2NA22IOTv00U97065tUNBQKEVXcaL0UJirtcqHlq8lN4pEm14ZokKXv8mUP8GkUKrOf37GhOugi/F/CQiILb57kIPrYPk="];
unsigned char salt[8]; //get the salt out
[test getBytes:salt range:NSMakeRange(8, 8)];
NSData *saltData = [NSData dataWithBytes:salt length:8];
unsigned char data[128-16]; // remove the Salted__ and the 8 character salt
[test getBytes:data range:NSMakeRange(8, 128-8)];
test = [NSData dataWithBytes:data length:128-8];
NSMutableData *aeskey = [NSMutableData dataWithData:[key dataUsingEncoding:NSUTF8StringEncoding]];
[aeskey appendData:saltData]; // add the salt to the end of the key?
NSData *test2 = [test decryptedAES256DataUsingKey:key error:nil]; //Using a NSData+CommonCrypto library
Any ideas on how to decrypt this properly?
EDIT: more information: this is code related to what I am trying to implement.
elsif ($header_mode eq 'salt') {
$self->{salt} = $self->_get_random_bytes(8) if $self->{make_random_salt};
defined (my $salt = $self->{salt}) or croak "No header_mode of 'salt' specified, but no salt value provided"; # shouldn't happen
length($salt) == 8 or croak "Salt must be exactly 8 bytes long";
my ($key,$iv) = $self->_salted_key_and_iv($self->{passphrase},$salt);
$self->{key} = $key;
$self->{civ} = $self->{iv} = $iv;
$result = "Salted__${salt}";
}
my $self = shift;
my ($pass,$salt) = #_;
croak "Salt must be 8 bytes long" unless length $salt == 8;
my $key_len = $self->{keysize};
my $iv_len = $self->{blocksize};
my $desired_len = $key_len+$iv_len;
my $data = '';
my $d = '';
while (length $data < $desired_len) {
$d = md5($d . $pass . $salt);
$data .= $d;
}
return (substr($data,0,$key_len),substr($data,$key_len,$iv_len));
Here is an implementation that I don't fully understand: http://pastebin.com/R0b1Z7GH http://pastebin.com/aYWFXesP
unsigned char salt[8]; //get the salt out
[test getBytes:salt range:NSMakeRange(8, 8)];
NSData *saltData = [NSData dataWithBytes:salt length:8];
unsigned char data[128-16]; // remove the Salted__ and the 8 character salt
[test getBytes:data range:NSMakeRange(8, 128-8)];
test = [NSData dataWithBytes:data length:128-8];
I think in your second block of code you are copying the wrong data. Try this:
unsigned char data[128-16]; // remove the Salted__ and the 8 character salt
[test getBytes:data range:NSMakeRange(16, 128-16)];
test = [NSData dataWithBytes:data length:128-16];
Your comment indicates that you want to skip both the Salted__ and the salt itself.
Note that I haven't got a clue where the salt should go -- that's up to the protocol that you're trying to integrate with -- so I hope you've got that well-documented from another source.
How do I decode a signed request in Objective-C?
Basically, how do I translate this Ruby code to Objective-C or C?
# Facebook sends a signed_requests to authenticate certain requests.
# http://developers.facebook.com/docs/authentication/signed_request/
def decode_signed_request(signed_request)
encoded_signature, encoded_data = signed_request.split('.')
signature = base64_url_decode(encoded_signature)
expected_signature = OpenSSL::HMAC.digest('sha256', #secret, encoded_data)
if signature == expected_signature
JSON.parse base64_url_decode(encoded_data)
end
rescue Exception => e
puts $!, $#
end
def base64_url_decode(string)
"#{string}==".tr("-_", "+/").unpack("m")[0]
end
SSToolKit Base64 decode NSString looks helpful.
Do you want to verify the signature on the data or just "decode" it? If it's the latter, you can just ignore the signature:
NSString *signedData = ...;
NSString *base64EncodedData = [[signedData componentsSeparatedByString:#"."] objectAtIndex:1];
NSString *jsonString = [NSString stringWithBase64String:base64EncodedData];
id jsonObject = ...;
I leave using the Facebook SDK and choosing a suitable JSON framework (I recommend JSONKit) up to you.
Your comment indicates that you want to verify the HMAC included with the message. In that case:
unsigned int length = 0;
unsigned char *expectedHmac = HMAC(EVP_sha256(), [key bytes], [key length], [base64EncodedData UTF8String], [base64EncodedData length], NULL, &length);
NSData *expectedHmacData = [NSData dataWithBytes:expectedHmac length:length];
// compare expected hmac