I'm trying to encrypt data with an RSA public key using openssl.
I have the Java implementation of what I need to do in Objective-C.
Here's what I have so far:
- (RSA *)rsaFromExponent:(NSString *)exponent modulus:(NSString *)modulus
{
RSA *rsa_pub = RSA_new();
const char *N = [modulus UTF8String];
const char *E = [exponent UTF8String];
if (!BN_hex2bn(&rsa_pub->n, N))
{
// TODO
}
printf("N: %s\n", N);
printf("n: %s\n", BN_bn2dec(rsa_pub->n));
if (!BN_hex2bn(&rsa_pub->e, E))
{
// TODO
}
printf("E: %s\n", E);
printf("e: %s\n", BN_bn2dec(rsa_pub->e));
return rsa_pub;
}
- (NSString *)cleanString:(NSString *)input
{
NSString *output = input;
output = [output stringByReplacingOccurrencesOfString:#"<" withString:#""];
output = [output stringByReplacingOccurrencesOfString:#">" withString:#""];
output = [output stringByReplacingOccurrencesOfString:#" " withString:#""];
return output;
}
// main code
NSString *exponentB64 = #"AQAB";
NSString *modulusB64 = #"AKDbnFpblq7LHfWDfGTR48B34MKaHQosMwVu8cCc6fH2pZ8Ypx/OgzG6VJlKHXeELtlo5tddBSJpwnkEQdvkkmwuOpCkacTTLon6EHqX4WwFW+waqHxmj419SxiDDlo9tsbg7vfFIMpKyGzq1zvTAN3TroW+MxogZfZD3/N6dNTzvBoXe/Ca1e/zVwYXKbiegLMjNwsruz/WvuMiNKTK4U3GEmb0gIODd1shAH10ube8Nrz/e1u9kr25VQ+7kZAFjnkPTp2AvNGYHQt35m1TRMQhTylVwTZqFkHC/jMt7WxuS8q7ftjM828wa1fEWTgWYrdkzmqZSK5CHBYSys/N1Ws=";
// 1. decode base64 (http://projectswithlove.com/projects/NSData_Base64.zip)
NSData *exponent = [NSData dataFromBase64String:exponentB64];
NSData *modulus = [NSData dataFromBase64String:modulusB64];
NSString *exponentHex = [self cleanString:[exponent description]];
NSString *modulusHex = [self cleanString:[modulus description]];
// 2. create RSA public key
RSA *rsa_pub = [self rsaFromExponent:exponentHex modulus:modulusHex];
NSString *user = #"TEST";
// 3. encode base 64
NSData *userData = [user dataUsingEncoding:NSASCIIStringEncoding];
NSString *userB64String = [userData base64EncodedString];
// 4. encrypt
const unsigned char *from = (const unsigned char *)[userB64String cStringUsingEncoding:NSASCIIStringEncoding];
int flen = strlen((const char *)from);
unsigned char *to = (unsigned char *) malloc(RSA_size(rsa_pub));
int padding = RSA_PKCS1_PADDING;
int result = RSA_public_encrypt(flen, from, to, rsa_pub, padding);
if (-1 == result)
{
NSLog(#"WAT?");
}
else
{
NSLog(#"from: %s", from); // echo VEVTVA==
NSLog(#"to: %s", to); // echo something strange with characters like: ~™Ÿû—...
}
// 5. encode base 64
NSString *cipherString = [NSString stringWithCString:(const char *)to
encoding:NSASCIIStringEncoding];
NSData *cipherData = [cipherString dataUsingEncoding:NSASCIIStringEncoding];
NSString *cipherDataB64 = [cipherData base64EncodedString];
NSLog(#"user encrypted b64: %#", cipherDataB64); // echo null :-(
In Java, I have no problem to base64 encode the encrypted data.
I'm sure I'm doing something wrong but I don't know where because it's not something I do everyday.
Or if you know another way to do this with iOS frameworks like Security.framework.
Thanks in advance.
Someone else helped me figure it out. I don't know why but I was assuming that the output buffer from RSA_public_encrypt function would be an ascii string. Though it's just bytes as the documentation says too. The char * type often leads me to think it's gonna store a string (it's so wrong I think it's the last time I make this kind of error).
So from step 5:
// 5. encode base 64
NSData *cipherData = [NSData dataWithBytes:(const void *)to length:result];
NSString *cipherDataB64 = [cipherData base64EncodedString];
NSLog(#"user encrypted b64: %#", cipherDataB64); // now echo the expected value
Related
We are facing problem while creating compressed file at iOS Device Document Directory, .tgz file is in Hex string transferring from pin-pad device to iPad iOS App at TCP socket layer. We used below HexToString function to convert that hex string and make file with .tgz. but at the end file is corrupted.
Can anyone please help us here, how to create compress file at iOS level with below hex string ? Please suggest us any code changes.
Note :- we had tried multiple NSStringEncoding technique, like ASCII, Unicode, Utf8, etc.
HEX String:-
1F8B08003058A8620203EDCA3B0A80301045D1594A5660265FB7E036065422A8453282CB57B4B2B112419CD3DCE2BD6966DD8F54925E4A975B62D22551EE741A2A5E199E80BBE8F1681DFDA5270BC6DB60D1398735A0092E0650082F580A53566A6F36F7BFFBFDA39A01841042FCD0062C8057FA00080000
we are using Xcode Version:13.1 and IOS Version 15.1 and above.
//Below function we used for creating .tgz file
//fileName here is abc.tgz which is compress file type
//content here is hex string mention aboved
+ (void)writeToLogFile:(NSString*)content fileName:(NSString*)fileNameString{
content = [NSString stringWithFormat:#"%#",content];
NSString *documentsDirectory = [NSHomeDirectory() stringByAppendingPathComponent:#"Documents"];
NSString *fileName = [documentsDirectory stringByAppendingPathComponent:fileNameString];
NSData *fileOriginalString = [self HextoString:content];
NSData *fileData = [fileOriginalString dataUsingEncoding:NSASCIIStringEncoding];
***//In alternative we also tried direct hex string to NSData type by calling below commentented method but it still failing
//NSData *fileData = [self dataFromHexString:content];***
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
NSError *error = nil;
[fileData writeToFile:fileName options:NSDataWritingAtomic error:&error];
NSLog(#"Write returned error: %#", [error localizedDescription]);
});
}
//Below function we used for Hex to String conversion
+(NSString*)HextoString:(NSString*)string{
#try{
NSMutableString * StrResult = [[NSMutableString alloc] init];
int i = 0;
while (i < [string length]){
NSString * hexChar = [string substringWithRange: NSMakeRange(i, 2)];
int value = 0;
sscanf([hexChar cStringUsingEncoding:NSASCIIStringEncoding], "%x", &value);
[StrResult appendFormat:#"%c", (char)value];
i+=2;
}
return StrResult;
}
#catch (NSException *exception){
[AELoggerManager info:[NSString stringWithFormat:#" %s EXCEPTION ::%#",__FUNCTION__,exception]];
}
}
+ (NSData *)dataFromHexString:(NSString *) string {
if([string length] % 2 == 1){
string = [#"0"stringByAppendingString:string];
}
const char *chars = [string UTF8String];
int i = 0, len = (int)[string length];
NSMutableData *data = [NSMutableData dataWithCapacity:len / 2];
char byteChars[3] = {'\0','\0','\0'};
unsigned long wholeByte;
while (i < len) {
byteChars[0] = chars[i++];
byteChars[1] = chars[i++];
wholeByte = strtoul(byteChars, NULL, 16);
[data appendBytes:&wholeByte length:2];
}
return data;
}
I am using these code to get a MD5+Base64 encrypt string, but when I run the code, it sometime can not return a true encryption string, not often.My encryption code like this:
+ (NSString *) md5: (NSData *) data
{
const char* original_str = (const char *)[data bytes];
unsigned char digist[CC_MD5_DIGEST_LENGTH]; //CC_MD5_DIGEST_LENGTH = 16
CC_MD5(original_str, (uint)strlen(original_str), digist);
NSData * md5data = [[NSData alloc] initWithBytes:digist length:sizeof(digist)];
NSString * result = [md5data base64EncodedStringWithOptions:0];
return result;
}
Try
const char *cStr = [#"fd" UTF8String];
unsigned char result[CC_MD5_DIGEST_LENGTH];
CC_MD5(cStr, (int)strlen(cStr), result);
NSMutableString *md5String = [NSMutableString stringWithCapacity:CC_MD5_DIGEST_LENGTH * 2];
for(int i = 0; i < CC_MD5_DIGEST_LENGTH; ++i) {
[md5String appendFormat:#"%02x", result[i]];
}
NSString *encodedString = [NSString stringWithString:md5String];
NSData *nsdata = [encodedString dataUsingEncoding:NSUTF8StringEncoding];
NSString *base64Encoded = [nsdata base64EncodedStringWithOptions:0];
I have got the solution. Just change this code
CC_MD5(original_str, (uint)strlen(original_str), digist);
to
CC_MD5(original_str, (CC_LONG)data.length, digist);
Swift
import CryptoKit
import CommonCrypto
func md5(data: Data) -> String {
let digest = Insecure.MD5.hash(data: data)
return Data(digest).base64EncodedString()
}
I have one quick question...
I am building a social media network site app and I need to hash the password NSString. How would I accomplish this? I have the password field on the app and would like to hash the string and encode it in SHA512 for the POST request.
Thanks in advance,
TechnologyGuy
Already answered: hash a password string using SHA512 like C#
But here's the copy-pasted code:
#include <CommonCrypto/CommonDigest.h>
+ (NSString *) createSHA512:(NSString *)source {
const char *s = [source cStringUsingEncoding:NSASCIIStringEncoding];
NSData *keyData = [NSData dataWithBytes:s length:strlen(s)];
uint8_t digest[CC_SHA512_DIGEST_LENGTH] = {0};
CC_SHA512(keyData.bytes, keyData.length, digest);
NSData *out = [NSData dataWithBytes:digest length:CC_SHA512_DIGEST_LENGTH];
return [out description];
}
Or if you prefer a hashed output, try this:
+(NSString *)createSHA512:(NSString *)string
{
const char *cstr = [string cStringUsingEncoding:NSUTF8StringEncoding];
NSData *data = [NSData dataWithBytes:cstr length:string.length];
uint8_t digest[CC_SHA512_DIGEST_LENGTH];
CC_SHA512(data.bytes, data.length, digest);
NSMutableString* output = [NSMutableString stringWithCapacity:CC_SHA512_DIGEST_LENGTH * 2];
for(int i = 0; i < CC_SHA512_DIGEST_LENGTH; i++)
[output appendFormat:#"%02x", digest[i]];
return output;
}
+ (NSData *)sha512:(NSData *)data {
unsigned char hash[CC_SHA512_DIGEST_LENGTH];
if ( CC_SHA512([data bytes], [data length], hash) ) {
NSData *sha1 = [NSData dataWithBytes:hash length:CC_SHA512_DIGEST_LENGTH];
return sha1;
}
return nil;
}
Put this in a category on NSData, or use it whatever way you like, the code remains the same.
You should've researched your question. I found an answer in one google search.
My code looks like this (using CommonCrypto/CommonHMAC.h):
- (NSString*) preperingCryptedData: (NSString*) data withKey: (NSString*) key {
NSData* dataToHash = [data dataUsingEncoding:NSUTF8StringEncoding];
NSData* keyData = [key dataUsingEncoding:NSUTF8StringEncoding];
NSLog(#"Utility: preperingCryptedData - Data to Crypt: %# and key %#\n...\n...\n...\n",dataToHash,keyData);
NSMutableData *dataHash = [NSMutableData dataWithLength:CC_SHA384_DIGEST_LENGTH];
CCHmac(kCCHmacAlgSHA384, keyData.bytes, keyData.length, dataToHash.bytes, dataToHash.length, dataHash.mutableBytes);
NSString* readyString = [[NSString alloc] initWithData:dataToHash encoding:NSUTF8StringEncoding];
NSLog(#"Utility: preperingCryptedData call, result :%#\n...\n...\n...\n",readyString);
return readyString;
}
When I used code from: Here I got my string decoded without the Key. What am I doing wrong? How it's possible to encode message without the key?
There are two problem with the code:
1) You are using dataToHash as the output instead of dataHash.
2) dataHash is not a UTF8 data representation so it can not be successfully converted into a NSString.
Agree with the accepted answer. Provide working code.
- (NSString *)sha384:(NSString*)data withKey:(NSString *)key {
NSData* dataToHash = [data dataUsingEncoding:NSUTF8StringEncoding];
NSData* keyData = [key dataUsingEncoding:NSUTF8StringEncoding];
unsigned char digest[CC_SHA384_DIGEST_LENGTH];
CCHmac(kCCHmacAlgSHA384, keyData.bytes, keyData.length, dataToHash.bytes, dataToHash.length, digest);
NSString *sha384Str;
NSMutableString *output = [NSMutableString stringWithCapacity:CC_SHA384_DIGEST_LENGTH * 2];
for(int i = 0; i < CC_SHA384_DIGEST_LENGTH; i++)
[output appendFormat:#"%02x", digest[i]];
sha384Str = output;
return sha384Str;
}
I have a requirement to integrate with a web service that serves as a login. The hash needs to be generated on the client. I am able to produce the correct hash as NSMutableData, but then I need to convert it to a string, without the spaces or brackets produced when the NSMutableData object is rendered as a string in the output console. I have read several posts, all seeming to say the same thing:
NSString *newstring = [[NSString alloc] initWithDSata:dataToConvert encoding:NSUTF8StringEncoding];
Unfortunately, this doesnt work for me. Using NSUTF8StringEncoding returns null. NSASCIIStringEncoding is even worse.
Here is my code:
NSString *password = [NSString stringWithFormat:#"%#%#", kPrefix, [self.txtPassword text]];
NSLog(#"PLAIN: %#", password);
NSData *data = [password dataUsingEncoding:NSASCIIStringEncoding];
NSMutableData *sha256Out = [NSMutableData dataWithLength:CC_SHA256_DIGEST_LENGTH];
CC_SHA256(data.bytes, data.length, sha256Out.mutableBytes);
NSString *preppedPassword = [[NSString alloc] initWithData:sha256Out encoding:NSASCIIStringEncoding];
NSLog(#"HASH: %#\n", preppedPassword);
How can I convert the NSMutableData to string?
My problem is that I need to from this
<7e8df5b3 17c99263 e4fe6220 bb75b798 4a41de45 44464ba8 06266397 f165742e>
to this
7e8df5b317c99263e4fe6220bb75b7984a41de4544464ba806266397f165742e
See How to convert an NSData into an NSString Hex string?
I use a slightly modified version myself:
#implementation NSData (Hex)
- (NSString *)hexRepresentationWithSpaces:(BOOL)spaces uppercase:(BOOL)uppercase {
const unsigned char *bytes = (const unsigned char *)[self bytes];
NSUInteger nbBytes = [self length];
// If spaces is true, insert a space every this many input bytes (twice this many output characters).
static const NSUInteger spaceEveryThisManyBytes = 4UL;
// If spaces is true, insert a line-break instead of a space every this many spaces.
static const NSUInteger lineBreakEveryThisManySpaces = 4UL;
const NSUInteger lineBreakEveryThisManyBytes = spaceEveryThisManyBytes * lineBreakEveryThisManySpaces;
NSUInteger strLen = 2 * nbBytes + (spaces ? nbBytes / spaceEveryThisManyBytes : 0);
NSMutableString *hex = [[NSMutableString alloc] initWithCapacity:strLen];
for (NSUInteger i = 0; i < nbBytes; ) {
if (uppercase) {
[hex appendFormat:#"%02X", bytes[i]];
} else {
[hex appendFormat:#"%02x", bytes[i]];
}
// We need to increment here so that the every-n-bytes computations are right.
++i;
if (spaces) {
if (i % lineBreakEveryThisManyBytes == 0) {
[hex appendString:#"\n"];
} else if (i % spaceEveryThisManyBytes == 0) {
[hex appendString:#" "];
}
}
}
return hex;
}
#end