i was implementing the in-app purchase.All i am doing in a apple sandbox i have done transaction completely and also apple is returning the response = 0 when i verify the receipt, but my question is where do i look for successful payment received. Which email id i will get mails like "you have received the amount from user1". ? or should i look to itune connect?
here is my code for receiving response:
- (BOOL)verifyReceipt:(SKPaymentTransaction *)transaction {
NSString *jsonObjectString = [self encode:(uint8_t *)transaction.transactionReceipt.bytes length:transaction.transactionReceipt.length];
NSString *completeString = [NSString stringWithFormat:#"http://test.clientarea.in/WS/two.php?receipt=%#", jsonObjectString];
NSLog(#"completestring%#",jsonObjectString);
NSURL *urlForValidation = [NSURL URLWithString:completeString];
NSMutableURLRequest *validationRequest = [[NSMutableURLRequest alloc] initWithURL:urlForValidation];
[validationRequest setHTTPMethod:#"GET"];
NSData *responseData = [NSURLConnection sendSynchronousRequest:validationRequest returningResponse:nil error:nil];
[validationRequest release];
NSString *responseString = [[NSString alloc] initWithData:responseData encoding: NSUTF8StringEncoding];
NSInteger response = [responseString integerValue];
NSLog(#"response string...%d",response);
[responseString release];
return (response == 0);
}
- (NSString *)encode:(const uint8_t *)input length:(NSInteger)length {
static char table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
NSMutableData *data = [NSMutableData dataWithLength:((length + 2) / 3) * 4];
uint8_t *output = (uint8_t *)data.mutableBytes;
for (NSInteger i = 0; i > 18) & 0x3F];
output[index + 1] = table[(value >> 12) & 0x3F];
output[index + 2] = (i + 1) > 6) & 0x3F] : '=';
output[index + 3] = (i + 2) > 0) & 0x3F] : '=';
}
return [[[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding] autorelease];}
You need to look in iTunes Connect. Apple generates reports by region (which they will send out to the registered account admin) some time after the month closes.
These reports are a bit opaque and will not give you specific device uniqueIdentifiers.
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 receiving data encrypted with SJCL into an iOS app where I need to decrypt it. The other end is using SJCL with the AES CCM mode which is not supported by the Apple's CommonCrypto so I use the VPCCMCrypt library for this. It is not possible to make any changes to the other side sending the SJCL cipher text.
Here are my methods to decrypt:
+ (NSData *)decryptSjcl:(NSDictionary *)cipher password:(NSString *)password {
if (cipher == nil || password == nil) {
return nil;
}
int version = [cipher[#"v"] intValue];
NSString *iv = cipher[#"iv"];
uint iter = [cipher[#"iter"] unsignedIntValue];
uint ks = [cipher[#"ks"] unsignedIntValue];
uint ts = [cipher[#"ts"] unsignedIntValue];
NSString *mode = cipher[#"mode"];
NSString *adata = cipher[#"adata"];
NSString *algorithm = cipher[#"cipher"];
NSString *salt = cipher[#"salt"];
NSString *ct = cipher[#"ct"];
if (version != 1 || ! [#"aes" isEqualToString:algorithm]) {
return nil;
}
NSData *rawIv = [[NSData alloc] initWithBase64EncodedString:iv options:0];
NSData *rawSalt = [[NSData alloc] initWithBase64EncodedString:salt options:0];
NSData *rawAdata = [[NSData alloc] initWithBase64EncodedString:adata options:0];
NSData *cipherData = [[NSData alloc] initWithBase64EncodedString:ct options:0];
NSData *key;
NSMutableData *decipheredData = nil;
if ([#"ccm" isEqualToString:mode]) {
key = [Cryptor sjclAesKeyForPassword:password salt:rawSalt iterations:iter keySize:ks];
decipheredData = [Cryptor decryptAesCcmData:cipherData iv:rawIv key:key adata:rawAdata tagSize:ts];
}
return decipheredData;
}
SJCL key generation:
+ (NSData *)sjclAesKeyForPassword:(NSString *)password salt:(NSData *)salt iterations:(uint)iterations keySize:(uint)keySizeBits {
NSMutableData *derivedKey = [NSMutableData dataWithLength:keySizeBits / 8];
int result = CCKeyDerivationPBKDF(kCCPBKDF2,
password.UTF8String,
[password lengthOfBytesUsingEncoding:NSUTF8StringEncoding],
salt.bytes,
salt.length,
kCCPRFHmacAlgSHA256,
iterations,
derivedKey.mutableBytes,
derivedKey.length);
NSAssert(result == kCCSuccess, #"Unable to create AES key for password: %d", result);
return derivedKey;
}
AES CCM decryption:
+ (NSMutableData *)decryptAesCcmData:(NSData *)cipherData iv:(NSData *)iv key:(NSData *)key adata:(NSData *)adata tagSize:(uint)tagSizeBits {
VPCCMCrypt *ccm = [[VPCCMCrypt alloc] initWithKey:key
iv:iv
adata:adata
tagLength:tagSizeBits / 8];
[ccm decryptDataWithData:cipherData
finishedBlock:^(NSData *data) {
NSString *result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(#"Decrypted SJCL message: %#", result);
}
errorBlock:^(NSError *error) {
NSLog(#"ERROR");
}];
return nil;
}
All the input data from the SJCL is correctly parsed (IV, salt, key size, tag size, PBKDF iterations, cipher text) and decoded to NSData from their Base64 encoded representation. Password is used the same. All data including the created AES key are not nil.
At the end it fails inside the VPCCMCrypt verifying the CCM tag (tags are different). Is there something wrong with the code above? Is there any other iOS/Objective-C/Swift library to decrypt AES CCM or even better the SJCL? I am not interested in a JavaScript wrapper of the SJCL library.
For testing I am using simple encrypted data from the SJCL's demo page.
EDIT:
As said in comments the SJCL send 16 bytes IV instead of max 12 bytes for the CCM mode and then internally clamps it to max 12 bytes when deciphering. Here is the updated decrypt method:
+ (NSData *)decryptSjcl:(NSDictionary *)cipher password:(NSString *)password {
if (cipher == nil || password == nil) {
return nil;
}
int version = [cipher[#"v"] intValue];
NSString *iv = cipher[#"iv"];
uint iter = [cipher[#"iter"] unsignedIntValue];
uint ks = [cipher[#"ks"] unsignedIntValue];
uint ts = [cipher[#"ts"] unsignedIntValue];
NSString *mode = cipher[#"mode"];
NSString *adata = cipher[#"adata"];
NSString *algorithm = cipher[#"cipher"];
NSString *salt = cipher[#"salt"];
NSString *ct = cipher[#"ct"];
if (version != 1 || ! [#"aes" isEqualToString:algorithm]) {
return nil;
}
NSMutableData *rawIv = [[NSMutableData alloc] initWithBase64EncodedString:iv options:0];
NSMutableData *rawSalt = [[NSMutableData alloc] initWithBase64EncodedString:salt options:0];
NSMutableData *rawAdata = [[NSMutableData alloc] initWithBase64EncodedString:adata options:0];
NSMutableData *cipherData = [[NSMutableData alloc] initWithBase64EncodedString:ct options:0];
NSData *key;
NSData *decipheredData = nil;
if ([#"ccm" isEqualToString:mode]) {
key = [Cryptor sjclAesKeyForPassword:password salt:rawSalt iterations:iter keySize:ks];
// Clamp the SJCL IV - They use a 16 byte IV for CCM mode which is against specification and they do a funky
// clamping. CCM mode IV should be max 13 bytes long. They almost always clamp it to 13 bytes but save the whole
// 16 bytes in their JSON container.
// for (L=2; L<4 && ol >>> 8*L; L++) {}
// if (L < 15 - ivl) { L = 15-ivl; }
// iv = w.clamp(iv,8*(15-L));
int64_t ivl = rawIv.length;
int64_t ol = cipherData.length - (ts / 8);
int64_t L = 2;
for (L = 2; L < 4 && ol >> 8*L; L++) {}
if (L < 15 - ivl) {
L = 15 - ivl;
}
NSRange subrange = NSMakeRange(0, (NSUInteger)(15 - L));
decipheredData = [Cryptor decryptAesCcmData:cipherData iv:[rawIv subdataWithRange:subrange] key:key adata:rawAdata tagSize:ts];
}
else {
decipheredData = nil;
}
return decipheredData;
}
One last missing thing is verifying the TAG, I am unable to do that. Any ideas?
SJCL doesn't use the whole (128/192/256bit) IV in AES-CCM mode, but the demo page shows it. Try it with less bytes.
Here you can find how the IV length calculation works:
http://bitwiseshiftleft.github.io/sjcl/doc/symbols/src/core_ccm.js.html
for (L=2; L<4 && ol >>> 8*L; L++) {}
if (L < 15 - ivl) { L = 15-ivl; }
iv = w.clamp(iv,8*(15-L));
I have googled a lot but enable to get Blowfish ECB algorithm with PKCS5 padding in Objective-C.
I have tried code from here but it is not giving me proper encrypted data. Even I have tried codes from here but it is not with PKSC5 padding.
Unfortunately I have to use Blowfish (no other option) to convert following JAVA code in Objective-C
String objVal=<the json>;
SecretKeySpec lKeySpec = new SecretKeySpec(lKey.getBytes("UTF8"),"Blowfish");
Cipher lCipher = Cipher.getInstance("Blowfish/ECB/PKCS5Padding");
lCipher.init(Cipher.ENCRYPT_MODE, lKeySpec);
byte[] lPassword = objVal.getBytes("UTF8");
byte[] lEncryptPassword = lCipher.doFinal(lPassword);
String lEncryptString = new BASE64Encoder().encode(lEncryptPassword);
StringBuffer nString = new StringBuffer();
for (int i = 0; i < lEncryptString.length(); i++) {
int a = lEncryptString.charAt(i);
if (a != 13 && a != 10 && !lEncryptString.substring(i, i + 1).equals(" ")){
nString.append(lEncryptString.charAt(i));
}
return nString.toString();
Then the encrypted json is encoded:
String returnData=<encrypted json>
byte[] inputBytes = returnData.getBytes();
returnData = DatatypeConverter.printBase64Binary(inputBytes);
Any one has tried and tested solution for Blowfish ECB algorithm with PKSC5 padding.
Thank you in advance.
I know this question is already (several times) asked but either not answered or not with PKCS5 padding
Example code:
Add Security.framework
#import <CommonCrypto/CommonCryptor.h>
+ (NSData *)doBlowfish:(NSData *)dataIn
context:(CCOperation)kCCEncrypt_or_kCCDecrypt
key:(NSData *)key
options:(CCOptions)options
iv:(NSData *)iv
error:(NSError **)error
{
CCCryptorStatus ccStatus = kCCSuccess;
size_t cryptBytes = 0;
NSMutableData *dataOut = [NSMutableData dataWithLength:dataIn.length + kCCBlockSizeBlowfish];
ccStatus = CCCrypt( kCCEncrypt_or_kCCDecrypt,
kCCAlgorithmBlowfish,
options,
key.bytes,
key.length,
(iv)?nil:iv.bytes,
dataIn.bytes,
dataIn.length,
dataOut.mutableBytes,
dataOut.length,
&cryptBytes);
if (ccStatus == kCCSuccess) {
dataOut.length = cryptBytes;
}
else {
if (error) {
*error = [NSError errorWithDomain:#"kEncryptionError"
code:ccStatus
userInfo:nil];
}
dataOut = nil;
}
return dataOut;
}
Test:
NSError *error;
NSData *key = [#"Blowfish" dataUsingEncoding:NSUTF8StringEncoding];
NSString *stringOriginal = #"TestData";
NSData *dataOriginal = [stringOriginal dataUsingEncoding:NSUTF8StringEncoding];;
NSLog(#"key %#", key);
NSLog(#"stringOriginal %#", stringOriginal);
NSLog(#"dataOriginal %#", dataOriginal);
NSData *dataEncrypted = [Test doBlowfish:dataOriginal
context:kCCEncrypt
key:key
options:kCCOptionPKCS7Padding | kCCOptionECBMode
iv:nil
error:&error];
NSLog(#"dataEncrypted %#", dataEncrypted);
NSString *encryptedBase64String = [dataEncrypted base64EncodedStringWithOptions:0];
NSLog(#"encryptedBase64String %#", encryptedBase64String);
NSData *dataToDecrypt = [[NSData alloc] initWithBase64EncodedString:encryptedBase64String options:0];
NSData *dataDecrypted = [Test doBlowfish:dataToDecrypt
context:kCCDecrypt
key:key
options:kCCOptionPKCS7Padding | kCCOptionECBMode
iv:nil
error:&error];
NSLog(#"dataDecrypted %#", dataDecrypted);
NSString *stringDecrypted = [[NSString alloc] initWithData:dataDecrypted encoding:NSUTF8StringEncoding];
NSLog(#"stringDecrypted %#", stringDecrypted);
Output:
key 426c6f77 66697368
stringOriginal TestData
dataOriginal 54657374 44617461
dataEncrypted ba5eb956 7e73ae1a b5513ea1 75a14019
encryptedBase64String ul65Vn5zrhrdmeYV9B5rQA==
dataDecrypted 54657374 44617461
stringDecrypted TestData
For Single Platform Integration i need to create a Base64 Signature https://singleplatform.jira.com/wiki/display/PubDocs/SinglePlatform+Publisher+Integration#SinglePlatformPublisherIntegration-BuildingValidURLs
here is ruby script to create Base64 Signature, which work now i want to create it in iOS.
require 'hmac-sha1'
require 'base64'
def make_signature(uri_path, params, client_id, secret)
padding_factor = (4 - secret.length % 4) % 4
secret += "=" * padding_factor
secret = secret.gsub(/[-_]/, {"-" => "+", "_" => "/"})
binary_key = Base64.decode64(secret)
params.update({"client" => client_id})
path = uri_path + "?" + params.collect{|k,v| "#{k}=#{v}"}.inject{|initial,cur| initial + "&" + cur}
digest = HMAC::SHA1.new(binary_key).update(path).digest
digest = Base64.encode64(digest).gsub(/[+\/]/, {"+" => "-", "/" => "_"}).delete("=")
return "#{path}&sig=#{digest}"
end
puts 'http://api.singleplatform.co' + make_signature('/locations/haru-7', {}, "YOUR CLIENT ID", "YOUR SECRET")
What I have tried
I have tried https://github.com/MealCatcher/objc-singleplatform it not working.
I have also tried Base64 & iOS 7 CommonHMAC.h framework.
//To HMAC-SHA1 Signing
static NSData *HMAC_SHA1(NSString *data, NSString *key) {
unsigned char buf[CC_SHA1_DIGEST_LENGTH];
CCHmac(kCCHmacAlgSHA1, [key UTF8String], [key length], [data UTF8String], [data length], buf);
return [NSData dataWithBytes:buf length:CC_SHA1_DIGEST_LENGTH];
}
//To Retrieve your private key For URL
NSString *uri_path = [NSString stringWithFormat:#"%#?client=%#",#"/locations/haru-7",#"clientID"];
NSMutableString *secret = [NSMutableString stringWithFormat:#"%#=",signingKey];
[secret stringByReplacingOccurrencesOfString:#"-" withString:#"+"];
[secret stringByReplacingOccurrencesOfString:#"_" withString:#"/"];
NSData *signature = HMAC_SHA1(uri_path, [secret base64DecodedString]);
NSString *base64Signature = [signature base64EncodedString];
[base64Signature stringByReplacingOccurrencesOfString:#"+" withString:#"-"];
[base64Signature stringByReplacingOccurrencesOfString:#"/" withString:#"_"];
Thanks in advance.
Full Solution:
https://github.com/ronakjangir47/SinglePlatformSignature
Here is an example as Objective-C methods. Note the separation of tasks into individual methods, each can be easily written & tested individually.
- (NSString *)signatureBase64 {
NSString *uri_path = [NSString stringWithFormat:#"%#?client=%#",#"/locations/haru-7",#"clientID"];
NSData *signature = [uri_path dataUsingEncoding:NSUTF8StringEncoding];
NSLog(#"signature Data: %#", signature);
NSString *signingKeyBase64 = #"c2lnbmluZ0tleQ==";
NSData *signingKey = [self decodeURLBase64String:signingKeyBase64];
NSLog(#"signingKey Data: %#", signingKey);
NSLog(#"signingKeyAscii: '%#'", [[NSString alloc] initWithData:signingKey encoding:NSUTF8StringEncoding]);
NSData *digest = [self hmacSha1:signature key:signingKey];
NSLog(#"digest Data: %#", digest);
NSString *signatureBase64 = [self encodeURLBase64Data:digest];
NSLog(#"signatureBase64: '%#'", signatureBase64);
return signatureBase64;
}
- (NSData *)decodeURLBase64String:(NSString *)string {
string = [string stringByReplacingOccurrencesOfString:#"-" withString:#"+"];
string = [string stringByReplacingOccurrencesOfString:#"_" withString:#"/"];
NSData *data = [[NSData alloc] initWithBase64Encoding:string];
return data;
}
- (NSString *)encodeURLBase64Data:(NSData *)data {
NSString *signatureBase64 = [data base64EncodedStringWithOptions:0];
signatureBase64 = [signatureBase64 stringByReplacingOccurrencesOfString:#"+" withString:#"-"];
signatureBase64 = [signatureBase64 stringByReplacingOccurrencesOfString:#"?" withString:#"_"];
return signatureBase64;
}
// Note there is no intermediate buffer, this is a simple pattern.
- (NSData *)hmacSha1:(NSData *)data key:(NSData *)key {
NSMutableData *hmac = [NSMutableData dataWithLength:CC_SHA1_DIGEST_LENGTH];
CCHmac( kCCHmacAlgSHA1,
key.bytes, key.length,
data.bytes, data.length,
hmac.mutableBytes);
return hmac;
}
NSLog output:
signatureData: <2f6c6f63 6174696f 6e732f68 6172752d 373f636c 69656e74 3d636c69 656e7449 44>
signingKeyBase64: 'c2lnbmluZ0tleQ=='
signingKey Data: <7369676e 696e674b 6579>
signingKeyAscii: 'signingKey'
digest Data: <8e4b88b6 111e3151 3b5d35d0 04e60cf9 8a984fb3>
signatureBase64: 'jkuIthEeMVE7XTXQBOYM-YqYT7M='
I'm trying to use GCDAsyncSocket in my iOS app. I've been following all the step provided in the CocoaAsyncSocket's wiki. Here is what I'm doing:
GCDAsyncSocket socket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()];
NSError *err = nil;
if (![socket connectToHost:#"192.168.0.129" onPort:2811 error:&err]) // Asynchronous!
{
// If there was an error, it's likely something like "already connected" or "no delegate set"
NSLog(#"I goofed: %#", err);
}
uint8_t buffer[2] = "1\n";
NSData *data = [NSData dataWithBytes: &buffer length: sizeof(buffer)];
[socket writeData:data withTimeout:10 tag:1];
I already included too frameworks dependences: Security & CFNetwork, and included in my class the respective delegate. Do I need any other configuration to use it?
When I run this example I get this error:
[NSMallocBlock bytes]: unrecognized selector sent to instance 0x6b7abe0
'NSInvalidArgumentException', reason: '-[NSMallocBlock bytes]: unrecognized selector sent to instance 0x6b7abe0'
And it occurs on this line of GCDAsyncSocket.m
const uint8_t *buffer = (const uint8_t *)[currentWrite->buffer bytes] + currentWrite->bytesDone;
try use this to convert your data, from string to data
+(NSData *) DataToHex: (NSString *) string
{
string = [string stringByReplacingOccurrencesOfString:#" " withString:#""];
int stringLength = string.length;
NSMutableData *hexStringArray = [[NSMutableData alloc] init];
[hexStringArray setLength:0];
unsigned char whole_byte;
char byte_chars[3] = {'\0','\0','\0'};
int i;
for (i=0; i < stringLength/2; i++)
{
byte_chars[0] = [string characterAtIndex:i*2];
byte_chars[1] = [string characterAtIndex:i*2+1];
whole_byte = strtol(byte_chars, NULL, 16);
[hexStringArray appendBytes:&whole_byte length:1];
} //this is auto way
return hexStringArray;
}