I've got the following code for decrypting the data:
-(NSString*)_decrypte:(NSString*)encrypted
{
NSString *decrypted;
NSData *enc = [[NSData alloc]initWithBase64EncodedString:encrypted options:0];
int len = (int)[enc length];
Byte *cipher = (Byte*)malloc(len);
memcpy((void *)cipher, [enc bytes], len);
Byte *iv = toIv(_ivCounter++, 16);
for(uint i = 0; i < 16; i++)
{
iv[i] = 0;
}
int outLen, plainttext_len, dec_success, tag_len = 128 / 8;
unsigned char *plaintext = (unsigned char*)malloc(len);
unsigned char *tag =(unsigned char*)malloc(tag_len);
int offset = len - (tag_len);
for(int i = 0; i < tag_len; i++)
{
tag[i] = cipher[i + offset];
}
EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
EVP_DecryptInit_ex(ctx, EVP_aes_128_gcm(), NULL, NULL, NULL);
EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, 16, (void *)tag);
EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, 16, NULL);
EVP_DecryptInit_ex(ctx, NULL, NULL, _sesKey, iv);
EVP_DecryptUpdate(ctx, NULL, &len, NULL, 0);
EVP_DecryptUpdate(ctx, plaintext, &outLen, cipher, len);
plainttext_len = outLen;
dec_success = EVP_DecryptFinal_ex(ctx, plaintext + outLen, &outLen);
EVP_CIPHER_CTX_free(ctx);
decrypted = [NSString stringWithFormat:#"%s", plaintext];
return decrypted;
}
For some reason the code doesn't decrypt the data right. The _sesKey is right and the IV is overwritten after the call to toIV to force the right iv for the first set of data and there is no AAD data needed for the decrypting. I've already done this in android(using the bouncycastle library), so I known for a fact that the _sesKey and the IV are correct. I don't know if anybody can help me by telling what goes wrong and why.
I found the mistake with some help, the problem is that the variable _sesKey was a pointer and during generating the key and decrypting the data, the memory the pointer was pointing to got whiped. So the _sesKey became invalid. So now a changed _sesKey to a normal byte array and now it works.
Related
I have a tool class. The tool class has written a method of decompression of lz4, but the decompression is controlled, and I don't know what is wrong (libcompression.tbd and #include "compression.h" both have). Below is the code:
+ (NSData *)getDecompressedData:(NSData *)compressed
{
size_t dst_buffer_size = 168*217;
uint8_t *dst_buffer = (uint8_t *)malloc(dst_buffer_size);
uint8_t *src_buffer = (uint8_t *)malloc(compressed.length);
size_t compressResultLength = compression_decode_buffer(dst_buffer, dst_buffer_size, src_buffer, dst_buffer_size, NULL, COMPRESSION_LZ4);
NSData *decompressed = [[NSData alloc] initWithBytes:dst_buffer length:compressResultLength];
return decompressed;
}
CompressResultLength this value is 0
I chose this algorithm incorrectly, COMPRESSION_LZ4 should not be selected, COMPRESSION_LZ4_RAW should be selected, the size of the target and the size of the source data were also wrong before the application. I will send the correct code below:
+ (NSData *)getDecompressedData:(NSData *)compressed{
size_t destSize = 217*168;
uint8_t *destBuf = malloc(sizeof(uint8_t) * destSize);
const uint8_t *src_buffer = (const uint8_t *)[compressed bytes];
size_t src_size = compressed.length;
size_t decompressedSize = compression_decode_buffer(destBuf, destSize, src_buffer, src_size,
NULL, COMPRESSION_LZ4_RAW);
MyLog(#"after decompressed. length = %d",decompressedSize) ;
NSData *data = [NSData dataWithBytesNoCopy:destBuf length:decompressedSize freeWhenDone:YES];
return data;}
The encryption algorithm that I need to implement needs to RSA encrypt a triple des key. However, I'm experiencing the following behaviour:
The triple Des is created without any issues.
The SecKeyGeneratePair is used to generate RSA public and private keys.
The triple Des key K1 and K2 values are encrypted with a public key that is generated.
I then look to decrypt the datablob created above using the private RSA key.
The decryption is successful! However, the K1 and K2 values seems corrupt.
Here is the code used to encrypt the K1 and K2 data:
- (NSData *)performRsaEncryptionOnData:(NSData *)message {
size_t cipherBufferSize = SecKeyGetBlockSize(publicKey);
size_t plainBufferSize = [message length];
uint8_t *plainBuffer = (uint8_t *)calloc(plainBufferSize, sizeof(uint8_t));
uint8_t *cipherBuffer = (uint8_t *)calloc(cipherBufferSize, sizeof(uint8_t));
strncpy( (char *)plainBuffer,[message bytes], plainBufferSize);
SecKeyEncrypt(publicKey, kSecPaddingPKCS1, plainBuffer, plainBufferSize, &cipherBuffer[0], &cipherBufferSize);
return [NSData dataWithBytesNoCopy:cipherBuffer length:cipherBufferSize];
}
Here is the code used to decrypt the data:
- (NSData *)performRsaDecryptionForDataBlob:(NSData *)encryptedData {
size_t plainTextBufferSize = 128;
size_t cipherBufferSize = [encryptedData length];
uint8_t *cipherBuffer = (uint8_t*)[encryptedData bytes];
uint8_t *plainBuffer = (uint8_t *)calloc(plainTextBufferSize, sizeof(uint8_t));
SecKeyDecrypt(privateKey, kSecPaddingPKCS1,cipherBuffer,cipherBufferSize,&plainBuffer[0],&plainTextBufferSize);
return [NSData dataWithBytesNoCopy:plainBuffer length:plainTextBufferSize];
}
Here is the results that I get before RSA encryption: K1K2 = <54b86c29 f9766b00 d90a6c51 1a80026a>, after the decryption this is what we have: K1K2 = <54b86c29 f9766b00 00000000 00000000>. Frankly I'm not entirely sure why this is occuring. Any ideas?
strncpy(..) don't work with binary data. Your key contains a 0 and strncpy(..) stops copying the rest of your key.
K1K2 = <54b86c29 f9766b00 d90a6c51 1a80026a>
^^
I tried to generate SHA256 in iOS using Arcane library with following data:
String: Amount=50&BillerID=59&ChannelID=2&Context=34|check|test&ReturnURL=https://uat.myfatoora.com/ReceiptPOC.aspx&TxnRefNum=000000000020003&UserName=DCS
Key: 71DD0F73AFFBB47825FF9864DDE95F3B
Result was 409dc622b3bef5c9fc46e45c3210111fcb4536d3a55833316fe0dc8154b3ea34
which I thought to be correct. However, the Windows counterpart is generating SHA256 using following code:
Windows Phone Source Code:
public static string HmacSha256(string secretKey, string value)
{
var msg = CryptographicBuffer.ConvertStringToBinary(value, BinaryStringEncoding.Utf8);
byte[] convertedHash = new byte[secretKey.Length / 2];
for (int i = 0; i < secretKey.Length / 2; i++)
{
convertedHash[i] = (byte)Int32.Parse(secretKey.Substring(i * 2, 2), System.Globalization.NumberStyles.HexNumber);
}
// Create HMAC.
var objMacProv = MacAlgorithmProvider.OpenAlgorithm(MacAlgorithmNames.HmacSha256);
CryptographicHash hash = objMacProv.CreateHash(convertedHash.AsBuffer());
hash.Append(msg);
return CryptographicBuffer.EncodeToHexString(hash.GetValueAndReset());
}
and the result is: 94a20ca39c8487c7763823ec9c918d9e38ae83cb741439f6d129bcdef9edba73 which is different from what I got. Can somebody help me with this and let me know what the above code is doing and how can I replicate it in iOS.
Edit:
iOS Source code
let key = self.md5(string: "71DD0F73AFFBB47825FF9864DDE95F3B")
let hash = HMAC.SHA256(str, key: key)
The key here is you need to convert your secret, which is a hex string, into NSData. In other words, NSData byte stream would "look" like the secret.
This should do what you want:
// Hex string to NSData conversion from here http://stackoverflow.com/questions/7317860/converting-hex-nsstring-to-nsdata
NSString *secret = #"71DD0F73AFFBB47825FF9864DDE95F3B";
NSData *dataIn = [#"Amount=50&BillerID=59&ChannelID=2&Context=34|check|test&ReturnURL=https://uat.myfatoora.com/ReceiptPOC.aspx&TxnRefNum=000000000020003&UserName=DCS" dataUsingEncoding:NSUTF8StringEncoding];
NSMutableData *macOut = [NSMutableData dataWithLength:CC_SHA256_DIGEST_LENGTH];
secret = [secret stringByReplacingOccurrencesOfString:#" " withString:#""];
NSMutableData *secretData = [[NSMutableData alloc] init];
unsigned char whole_byte;
char byte_chars[3] = {'\0','\0','\0'};
int i;
for (i=0; i < [secret length]/2; i++) {
byte_chars[0] = [secret characterAtIndex:i*2];
byte_chars[1] = [secret characterAtIndex:i*2+1];
whole_byte = strtol(byte_chars, NULL, 16);
[secretData appendBytes:&whole_byte length:1];
}
CCHmac(kCCHmacAlgSHA256, secretData.bytes, secretData.length, dataIn.bytes, dataIn.length, macOut.mutableBytes);
NSMutableString *stringOut = [NSMutableString stringWithCapacity:macOut.length];
const unsigned char *macOutBytes = macOut.bytes;
for (NSInteger i=0; i<macOut.length; ++i) {
[stringOut appendFormat:#"%02x", macOutBytes[i]];
}
NSLog(#"dataIn: %#", dataIn);
NSLog(#"macOut: %#", macOut);
NSLog(#"stringOut: %#", stringOut);
Output:
2016-09-27 20:18:54.181 JKS[27562:5321334] dataIn: <416d6f75 6e743d35 30264269 6c6c6572 49443d35 39264368 616e6e65 6c49443d 3226436f 6e746578 743d3334 7c636865 636b7c74 65737426 52657475 726e5552 4c3d6874 7470733a 2f2f7561 742e6d79 6661746f 6f72612e 636f6d2f 52656365 69707450 4f432e61 73707826 54786e52 65664e75 6d3d3030 30303030 30303030 32303030 33265573 65724e61 6d653d44 4353>
2016-09-27 20:18:54.181 JKS[27562:5321334] macOut: <94a20ca3 9c8487c7 763823ec 9c918d9e 38ae83cb 741439f6 d129bcde f9edba73>
2016-09-27 20:18:54.181 JKS[27562:5321334] stringOut: 94a20ca39c8487c7763823ec9c918d9e38ae83cb741439f6d129bcdef9edba73
Updated with Swift (code should be cleaned up)
// http://stackoverflow.com/questions/29799361/generate-a-hmac-swift-sdk8-3-using-cchmac
func generateHMAC(key: String, data: String) -> String {
let keyData = key.dataFromHexadecimalString()! as NSData
let dataIn = data.data(using: .utf8)! as NSData
var result: [CUnsignedChar]
result = Array(repeating: 0, count: Int(CC_SHA256_DIGEST_LENGTH))
CCHmac(CCHmacAlgorithm(kCCHmacAlgSHA256), keyData.bytes, keyData.length, dataIn.bytes, dataIn.length, &result)
let hash = NSMutableString()
for val in result {
hash.appendFormat("%02hhx", val)
}
return hash as String
}
You can use this extension to convert the hex string to Data
// Modified slightly http://stackoverflow.com/questions/26501276/converting-hex-string-to-nsdata-in-swift
extension String {
func dataFromHexadecimalString() -> Data? {
var data = Data(capacity: characters.count / 2)
let regex = try! NSRegularExpression(pattern: "[0-9a-f]{1,2}", options: .caseInsensitive)
regex.enumerateMatches(in: self, options: [], range: NSMakeRange(0, characters.count)) { match, flags, stop in
let byteString = (self as NSString).substring(with: match!.range)
var num = UInt8(byteString, radix: 16)
data.append(&num!, count: 1)
}
return data
}
}
And to use do something like:
let secret = "71DD0F73AFFBB47825FF9864DDE95F3B"
let value = "Amount=50&BillerID=59&ChannelID=2&Context=34|check|test&ReturnURL=https://uat.myfatoora.com/ReceiptPOC.aspx&TxnRefNum=000000000020003&UserName=DCS"
print("\(generateHMAC(key: secret, data: value))")
Your output should be 94a20ca39c8487c7763823ec9c918d9e38ae83cb741439f6d129bcdef9edba73
You will need #import <CommonCrypto/CommonCrypto.h> in your bridging header.
The Windows code takes the string, interprets it as a hexadecimal number, and converts two characters a time into one byte.
Your Mac code most like takes the string as it is. Since the key starts with "71", your windows code takes that as a single byte with value 0x71 = 129, your Mac code takes it as two bytes with values '7' = 55 and '1' = 49.
All you need to do is convert the bytes on the Mac exactly as you do it on Windows. You might have to do the unthinkable and look at the source code of the Mac library to see how it does the actual hash calculation.
#import <CommonCrypto/CommonHMAC.h>
+ (NSString *)hmacSHA256EncryptString{
NSString * parameterSecret = #"input secret key";
NSString *plainString = #"input encrypt content string";
const char *secretKey = [parameterSecret cStringUsingEncoding:NSUTF8StringEncoding];
const char *plainData = [plainString cStringUsingEncoding:NSUTF8StringEncoding];
unsigned char cHMAC[CC_SHA256_DIGEST_LENGTH];
CCHmac(kCCHmacAlgSHA256, secretKey, strlen(secretKey), plainData, strlen(plainData), cHMAC);
NSData *HMACData = [NSData dataWithBytes:cHMAC length:sizeof(cHMAC)];
const unsigned char *bufferChar = (const unsigned char *)[HMACData bytes];
NSMutableString *hmacString = [NSMutableString stringWithCapacity:HMACData.length * 2];
for (int i = 0; i < HMACData.length; ++i){
[hmacString appendFormat:#"%02x", bufferChar[i]];
}
return hmacString;
}
I have two methods that create a sha1 hash from a string. Using the same input data this algorithms create different hashes, however they should create the same hashes.
In swift (creates 617fb90f14f2eacecc333d558237bf8bb9fc85f7):
static func sha1FromMessage(message: String) -> String {
let cKey = RestUtils.API_KEY.cStringUsingEncoding(NSASCIIStringEncoding)!
let cData = message.cStringUsingEncoding(NSUTF8StringEncoding)!
var cHMAC = [CUnsignedChar](count: Int(CC_SHA1_DIGEST_LENGTH), repeatedValue: 0)
CCHmac(CCHmacAlgorithm(kCCHmacAlgSHA1), cKey, UInt(cKey.count), cData, UInt(cData.count), &cHMAC)
let output = NSMutableString(capacity: Int(CC_SHA1_DIGEST_LENGTH))
for byte in cHMAC {
output.appendFormat("%02hhx", byte)
}
return output
}
and obj-c (creates d80b816f0b46d5211b6d9487089597e181717ea6)
+(NSString *)sha1FromMessage:(NSString *)message{
const char *cKey = [API_KEY cStringUsingEncoding:NSASCIIStringEncoding];
const char *cData = [message cStringUsingEncoding:NSUTF8StringEncoding];
unsigned char cHMAC[CC_SHA1_DIGEST_LENGTH];
CCHmac(kCCHmacAlgSHA1, cKey, strlen(cKey), cData, strlen(cData), cHMAC);
NSData *HMACData = [NSData dataWithBytes:cHMAC length:sizeof(cHMAC)];
const unsigned char *buffer = (const unsigned char *)[HMACData bytes];
NSMutableString *HMAC = [NSMutableString stringWithCapacity:HMACData.length * 2];
for (int i = 0; i < HMACData.length; ++i){
[HMAC appendFormat:#"%02hhx", buffer[i]];
}
return HMAC;
}
I would like the swift method to return the same hash as the obj-c method. Any ideas where the problem is?
The reason is that cData created by
let cData = message.cStringUsingEncoding(NSUTF8StringEncoding)!
includes the terminating NUL-character of the message string and that is counted in
UInt(cData.count) as well. You could fix that by using UInt(strlen(cData)) instead,
as in your Objective-C code.
But a better solution is to convert the input strings
to NSData objects instead:
let cKey = RestUtils.API_KEY.dataUsingEncoding(NSASCIIStringEncoding)!
let cData = message.dataUsingEncoding(NSUTF8StringEncoding)!
var cHMAC = [CUnsignedChar](count: Int(CC_SHA1_DIGEST_LENGTH), repeatedValue: 0)
CCHmac(CCHmacAlgorithm(kCCHmacAlgSHA1), cKey.bytes, UInt(cKey.length), cData.bytes, UInt(cData.length), &cHMAC)
With this modification, Swift and Objective-C code produce the same message digest.
I am recieving the Encrypted data by server (BLOWFISH ALGORITHM) , I have to decrypt it by using blowfish algorithm in IOS.
you can donwload my code from here : https://www.dropbox.com/s/nswsm7des7isgd5/BlowfishTest-4.zip
I am struggling from 2 days with this task , I try lot of links and find few useful :
Blowfish Source code
How to implement Blowfish algorithm in iOS
http://www.codeding.com/articles/blowfish-encryption-algorithm-for-iphone
In third link, i got ECB ( I have to decrypt using ECB). but this code also not gives correct output after decryption.
I am using a online tool for testing and this shows correct output : http://www.tools4noobs.com/online_tools/decrypt/
Key = 20zE1E47BE57$51
Input value is = aed5c110d793f850521a4dd3a56a70d9
Algorithm = BLOWFISH
Mode = ECB
Decode the input using= Hexa
output = aYzY1380188405 ( this is correct output which i want)
and I am getting : ¹àÀhÒ¢º¹iÂF
Here is my code :
//Mode selected by default in nib: “ECB”
NSString *modeString = [encryptionModeControl titleForSegmentAtIndex:encryptionModeControl.selectedSegmentIndex];
BlowfishAlgorithm *blowFish = [BlowfishAlgorithm new];
[blowFish setMode:[BlowfishAlgorithm buildModeEnum:modeString]];
[blowFish setKey:key];
[blowFish setInitVector:initVector];
[blowFish setupKey];
NSString *cipherText = cipherTextView.text;
NSString *plainText = [blowFish decrypt:cipherText];
NSLog(#"cipher-text: %#", cipherText);
NSLog(#"plain-text: %#", plainText);
Note : Server side data is Encrypted using BLOWFISH in ECB mode, and converted to hexadecimal notation.
1) Source of Blowfish routines from David Madore: ftp://quatramaran.ens.fr/pub/madore/misc/blowfish.c
Pls note that in this source .h part should be separated from the .c file.
2) To use Pandora API we have to use the passwords given by its wiki page here:
http://pan-do-ra-api.wikia.com/wiki/Json/5/partners
Currently decrypt password is: 20zE1E47BE57$51
3) Use this code snippet (standing on great programmers' shoulders) - original Pandora API implementation is here: https://github.com/alexcrichton/hermes
In AppDelegate.h (for simplicity)
#define PARTNER_DECRYPT "20zE1E47BE57$51"
...
-(NSData*) PandoraDecrypt:(NSString*) string;
In AppDelegate.m
static char h2i[256] = {
['0'] = 0, ['1'] = 1, ['2'] = 2, ['3'] = 3, ['4'] = 4, ['5'] = 5, ['6'] = 6,
['7'] = 7, ['8'] = 8, ['9'] = 9, ['a'] = 10, ['b'] = 11, ['c'] = 12,
['d'] = 13, ['e'] = 14, ['f'] = 15
};
static void appendByte(unsigned char byte, void *_data) {
NSMutableData *data = (__bridge NSMutableData*) _data;
NSLog(#"pre: %#", data);
[data appendBytes:&byte length:1];
NSLog(#"post: %#", data);
}
-(NSData*) PandoraDecrypt:(NSString*) string {
struct blf_ecb_ctx ctx;
NSMutableData *mut = [[NSMutableData alloc] init];
Blowfish_ecb_start(&ctx, FALSE, (unsigned char*) PARTNER_DECRYPT,
sizeof(PARTNER_DECRYPT) - 1, appendByte,
(__bridge void*) mut);
const char *bytes = [string cStringUsingEncoding:NSASCIIStringEncoding];
int len = [string lengthOfBytesUsingEncoding:NSASCIIStringEncoding];
int i;
for (i = 0; i < len; i += 2) {
NSLog(#"%c, %c, %d, %d", bytes[i], bytes[i+1], h2i[(int) bytes[i]] * 16, h2i[(int) bytes[i + 1]]);
Blowfish_ecb_feed(&ctx, h2i[(int) bytes[i]] * 16 + h2i[(int) bytes[i + 1]]);
}
Blowfish_ecb_stop(&ctx);
return mut;
}
And you can use this like:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
NSLog(#"%#", [NSString stringWithCString:[
[self PandoraDecrypt:#"aed5c110d793f850521a4dd3a56a70d9"] bytes]
encoding:NSASCIIStringEncoding]);
return YES;
}
So it was mainly a research from my side, pls give credit to implementers of the Blowfish api and the pandora api ;-)
Also my NSLogs are for research purpose, it highlights how the decryption works.