I have to create a amazon MWS integration with an iOS application the issue is that I am not able to create and sign the request please help me providing some code sample would be very good if you have any.
I have tried with going through documentation and creating the string but it says that the signature is invalid
First of all You have to include the Crypto definitions to digest your Request
#import <CommonCrypto/CommonHMAC.h>
By using this function You can digest Your request. The key is the secret key provided by Amazon
NSString *calcSignature(NSString *aString, NSString *key)
{
const char *cKey = [key cStringUsingEncoding: NSUTF8StringEncoding];
const char *cData = [aString cStringUsingEncoding: NSUTF8StringEncoding];
// Calculate SHA256-signature
unsigned char cHMAC[CC_SHA256_DIGEST_LENGTH];
CCHmac(kCCHmacAlgSHA256, cKey, strlen(cKey), cData, strlen(cData), cHMAC);
NSData *HMAC = [[NSData alloc] initWithBytes:cHMAC
length:sizeof(cHMAC)];
// return Base64 encoded
return [HMAC base64EncodedStringWithOptions:0];
}
Digest the following sample requestString
POST /Feeds/2009-01-01 HTTP/1.1
Content-Type: x-www-form-urlencoded
Host: mws.amazonservices.com
User-Agent: <Your User Agent Header>
AWSAccessKeyId=0PExampleR2
&Action=CancelFeedSubmissions
&FeedSubmissionIdList.Id.1=1058369303
&FeedTypeList.Type.1=_POST_PRODUCT_DATA_
&FeedTypeList.Type.2=_POST_PRODUCT_PRICING_DATA_
&MWSAuthToken=amzn.mws.4ea38b7b-f563-7709-4bae-87aeaEXAMPLE
&Marketplace=ATExampleER
&SellerId=A1ExampleE6
&SignatureMethod=HmacSHA256
&SignatureVersion=2
&Timestamp=2009-02-04T17%3A34%3A14.203Z
&Version=2009-01-01
Now You can calc the signature
NSString *signatureString = calcSignature(requestString, amazonSecretKey);
These signature is appended to the request and You should get the result. You can test a little and control if You sending the correct signature by using Amazon Scratchpad.
Related
// Code to decrypt value
{
NSString *dataString = #"8T79ubuRfEwpfSOO1yr3Q+nbsla4J7VqFCe4THnPOGxjk37+2QgdLUgq5yWqLtx+";
NSString *base64Key = #"82a645babc6vd41c9a2cb4d0d3ba17ad";
NSString *base64KeyIv = #"acf30ad62b693849";
NSData *key = [[NSData alloc] initWithBase64EncodedString:base64Key options:0];
NSData *keyiv = [[NSData alloc] initWithBase64EncodedString:base64KeyIv options:0];
NSData *data = [[NSData alloc] initWithBase64EncodedString:dataString options:0];
NSData *encryptedData = [ViewController crypt:data
iv:keyiv
key:key
context:kCCDecrypt];
NSString *decryptText = [[NSString alloc] initWithData:encryptedData
encoding:NSUTF8StringEncoding];
NSLog(#"Decrypted Result: %#", decryptText); //here getting NULL
}
I am getting null value while decryption.Please help me where I am wrong. AES256 CBC encryption/decryption in objective C. Getting null value in decryption. I am already having the encrypted value with me.
There are likely several errors here, and it's unclear what your -crypt:iv:key:context: method does. Do you know for certain that your encryption system exactly matches your -crypt:iv:key:context: method?
At a start, you're getting nil because the output isn't UTF-8 (because it's almost certainly corrupted due to passing the wrong key and IV).
Next, your crypt method should be generating errors because what you're passing is invalid, so you need to check those errors. They would likely tell you what's wrong.
At a minimum, you are decoding the key and IV incorrectly. If they're in Base64, they're the wrong length. They look like they're just UTF-8/ASCII encoded (which is a security issue, but your system may just be insecure). In Base64, this key is 24 bytes, while in ASCII it's 32 bytes (which is the correct key length).
If that's the only problem, then the fix would be:
NSData *key = [base64Key dataUsingEncoding:NSUTF8StringEncoding];
NSData *keyiv = [base64KeyIv dataUsingEncoding:NSUTF8StringEncoding];
(Ideally you'd rename the "base64..." identifier since these aren't Base64 encoded. dataString does appear to be Base64 encoded.)
I have been working on this for a while, but can not find a way to tackle the problem. Hopefully one of you can tell me what I am missing.
I am using NSURLConnection to download base64 encoded data containing AES128 encrypted data. What I have is the key, see code, and the knowledge that the first 16 characters of the encrypted data is the IV. What I want is to decode the data and then decrypt it using the key and iv extracted. This is what I have so far:
- (void) connectionDidFinishLoading:(NSURLConnection *) connection {
NSLog(#"Succeeded! Downloaded %d bytes of data", downloadData.length);
NSData *decoded_EncryptedData = [downloadData base64EncodedDataWithOptions:0];
NSString *decoded_EncryptedString = [[NSString alloc] initWithData: decoded_EncryptedData encoding:NSUTF8StringEncoding];
const void *key = #"0000000000000000000000000000000"; // key of length 32 char -> i know standard format for AES128 encryption is 16, maybe this requires 256 AES decryption
const void *iv = (__bridge const void *)([decoded_EncryptedString substringWithRange:NSMakeRange(0,16)]);
NSString *encryptedString = [decoded_EncryptedString substringWithRange:NSMakeRange(16, decoded_EncryptedString.length-16)];
// Now I have no idea what needs to happen, but from online research I found it should be something like this:
NSData encryptedData = [encryptedString dataUsingEncoding:NSUTF8StringEncoding]; // Writing it back into a data file
// Find size of returned data
size_t Size = encryptedData.length + kCCBlockSizeAES128;
// Initialise returned data
NSMutableData *decryptedData = [NSMutableData dataWithLength:Size];
// allocate variable to numBytesDecrypted
size_t numBytesDecrypted;
CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt, kCCAlgorithmAES128, 0, KCCKeySizeAES128, iv,
[encryptedData bytes], [encryptedData length], [decryptedData bytes], [decryptedData length],
&numBytesDecrypted);
// Now I test whether the decryption process was successful:
if (cryptStatus == kCCSuccess) {
NSLog(#"Successfully decrypted);
NSString *decryptedString = [[NSString alloc] initWithData:decryptedData encoding: NSUTF8StringEncoding];
}
}
The above code does display Successfully decrypted, however the string return null and size 0. Could someone please help me solve this? I would be so grateful.
Kind regards,
Lennaert
You have many problems.
You really need to know if the encryption is AES128 or AES256.
Encryption is data based, not string based. The conversion to a string decoded_EncryptedString is incorrect not should not be done.
The key is an issue, using a string is generally a bad idea, it is expected to be data bytes. Possibly the key is specified in hex so 32 hex characters would be 128 bits. If so conversion to data will be required.
'iv' and encryptedString are strings but they should be data, this a result of 2 above.
The key is not passed to CCCrypt.
Padding is generally used since the data is rarely exactly a block size in length, you probably need to specify PKCS7 padding to CCCrypt. You need to know if padding was used and if so was it PKCS7, php for example uses non-standard padding.
If PKCS7 padding is used the result must be trimmed to the length based on the variable numBytesDecrypted. If some other padding is used that must be trimmed.
If you want more help please supply test data and the result.
Finally, try and check back more frequently.
Previously I did Triple DES encryption to encrypt some data using a string key file, by defining a method
+ (NSData *)tripleDESEncryptWithKey:(NSString *)key dataToEncrypt:(NSData*)convertedData {}.
Now, similarly I am doing AES 256 encryption. But this time, I can not use a string as the key. I need to get NSData from a file in resources using
NSData *keyData = [NSData dataWithContentsOfFile:keyPath];
As I need to pass this key as parameter, I tried to convert it into string with
NSString *key = [[NSString alloc] initWithData:keyData encoding:NSUTF8StringEncoding];
but it returned NULL. So, How to use the Data key for AES 256 encryption ?
EDIT: I got that I should not use UTF8 encoding as the data file was made by Base64 encoding of a string. So Now the question is, how to get the string key using Base64 from keyData ?
If key variable returned NULL. Try to use like this.
NSString* key = [NSString stringWithUTF8String:[keyData bytes]];
Refer to KennyTM's Answer
UPDATE 1: You can also read the string directly from your file without convert in NSData
By NSFileHandle:
NSString * path = #"your key file path";
NSFileHandle * fileHandle = [NSFileHandle fileHandleForReadingAtPath:path];
NSData * buffer = nil;
while ((buffer = [fileHandle readDataOfLength:1024])) {
//do something with buffer
}
or use NSString
NSString * key = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil];
Refer to Dave DeLong's Answer
Note: Ensure your keyPath variable , Is it correct in the format of full or relative path?
UPDATE 2: You can also deal with Base64 Encoding with Matt Gallagher NSData+Base64 Class&Header (See also his blog there)
For encode base64
NSString * key = [[path dataUsingEncoding:NSUTF8StringEncoding] base64EncodedString];
Hope it helps you!
Read the file:
NSData* myData = [NSData dataWithContentsOfFile:myFileWithPath];
Then use one of the implementations in this post:
Base64 encoding options on the Mac and iPhone
to do your Base64 conversion.
Note: simply sticking your decryption key into a file is a bad idea. Optimally, the key would be stored securely by being encrypted by the user's own key.
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 :)
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