i have a code in c# for aes decryption
i want make same encryption result by objective-c
but i failed.. help me
i can fix objective-c code, what can i for this?
c# for decrypt
private static readonly string AES_KEY = "asdfasdfasdfasdf";
private static readonly int BUFFER_SIZE = 1024 * 4;
private static readonly int KEY_SIZE = 128;
private static readonly int BLOCK_SIZE = 128;
static public string Composite(string value)
{
using (AesManaged aes = new AesManaged())
using (MemoryStream ims = new MemoryStream(Convert.FromBase64String(value), false))
{
aes.KeySize = KEY_SIZE;
aes.BlockSize = BLOCK_SIZE;
aes.Mode = CipherMode.CBC;
aes.Key = Encoding.UTF8.GetBytes(AES_KEY);
byte[] iv = new byte[aes.IV.Length];
ims.Read(iv, 0, iv.Length);
aes.IV = iv;
using (ICryptoTransform ce = aes.CreateDecryptor(aes.Key, aes.IV))
using (CryptoStream cs = new CryptoStream(ims, ce, CryptoStreamMode.Read))
using (DeflateStream ds = new DeflateStream(cs, CompressionMode.Decompress))
using (MemoryStream oms = new MemoryStream())
{
byte[] buf = new byte[BUFFER_SIZE];
for (int size = ds.Read(buf, 0, buf.Length); size > 0; size = ds.Read(buf, 0, buf.Length))
{
oms.Write(buf, 0, size);
}
return Encoding.UTF8.GetString(oms.ToArray());
}
}
}
objective-c for encrypt
- (NSString *)AES128EncryptWithKey:(NSString *)key
{
NSData *plainData = [self dataUsingEncoding:NSUTF8StringEncoding];
NSData *encryptedData = [plainData AES128EncryptWithKey:key];
NSString *encryptedString = [encryptedData stringUsingEncodingBase64];
return encryptedString;
}
#import "NSData+AESCrypt.h"
#import <CommonCrypto/CommonCryptor.h>
static char encodingTable[64] =
{
'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P',
'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f',
'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v',
'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/'
};
#implementation NSData (AESCrypt)
- (NSData *)AES128EncryptWithKey:(NSString *)key
{
// 'key' should be 16 bytes for AES128
char keyPtr[kCCKeySizeAES128 + 1]; // room for terminator (unused)
bzero( keyPtr, sizeof( keyPtr ) ); // fill with zeroes (for padding)
// fetch key data
[key getCString:keyPtr maxLength:sizeof( keyPtr ) encoding:NSUTF8StringEncoding];
NSUInteger dataLength = [self length];
//See the doc: For block ciphers, the output size will always be less than or
//equal to the input size plus the size of one block.
//That's why we need to add the size of one block here
size_t bufferSize = dataLength + kCCBlockSizeAES128;
void *buffer = malloc( bufferSize );
size_t numBytesEncrypted = 0;
CCCryptorStatus cryptStatus = CCCrypt( kCCEncrypt, kCCAlgorithmAES128, kCCModeCBC | kCCOptionPKCS7Padding,
keyPtr, kCCKeySizeAES128,
NULL /* initialization vector (optional) */,
[self bytes], dataLength, /* input */
buffer, bufferSize, /* output */
&numBytesEncrypted );
if( cryptStatus == kCCSuccess )
{
//the returned NSData takes ownership of the buffer and will free it on deallocation
return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
}
free( buffer ); //free the buffer
return nil;
}
- (NSString *)base64Encoding
{
const unsigned char *bytes = [self bytes];
NSMutableString *result = [NSMutableString stringWithCapacity:self.length];
unsigned long ixtext = 0;
unsigned long lentext = self.length;
long ctremaining = 0;
unsigned char inbuf[3], outbuf[4];
unsigned short i = 0;
unsigned short charsonline = 0, ctcopy = 0;
unsigned long ix = 0;
while( YES )
{
ctremaining = lentext - ixtext;
if( ctremaining <= 0 ) break;
for( i = 0; i < 3; i++ )
{
ix = ixtext + i;
if( ix < lentext ) inbuf[i] = bytes[ix];
else inbuf [i] = 0;
}
outbuf [0] = (inbuf [0] & 0xFC) >> 2;
outbuf [1] = ((inbuf [0] & 0x03) << 4) | ((inbuf [1] & 0xF0) >> 4);
outbuf [2] = ((inbuf [1] & 0x0F) << 2) | ((inbuf [2] & 0xC0) >> 6);
outbuf [3] = inbuf [2] & 0x3F;
ctcopy = 4;
switch( ctremaining )
{
case 1:
ctcopy = 2;
break;
case 2:
ctcopy = 3;
break;
}
for( i = 0; i < ctcopy; i++ )
[result appendFormat:#"%c", encodingTable[outbuf[i]]];
for( i = ctcopy; i < 4; i++ )
[result appendString:#"="];
ixtext += 3;
charsonline += 4;
}
return [NSString stringWithString:result];
}
------------------------------------------------------------
------------------------------------------------------------
Related
I'm trying to decode aac data with AudioToolbox in iOS environment. I consulted this thread.
'AudioConverterNew' function call succeed but AudioConverterFillComplexBuffer returns error code 1852797029, kAudioCodecIllegalOperationError.
I'm trying to find my mistakes. Thank you for reading.
- (void)initAudioToolBox {
HCAudioAsset* asset = [self.provider getAudioAsset];
AudioStreamBasicDescription outFormat;
memset(&outFormat, 0, sizeof(outFormat));
outFormat.mSampleRate = 44100;
outFormat.mFormatID = kAudioFormatLinearPCM;
outFormat.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger;
outFormat.mBytesPerPacket = 2;
outFormat.mFramesPerPacket = 1;
outFormat.mBytesPerFrame = 2;
outFormat.mChannelsPerFrame = 1;
outFormat.mBitsPerChannel = 16;
outFormat.mReserved = 0;
AudioStreamBasicDescription inFormat;
memset(&inFormat, 0, sizeof(inFormat));
inFormat.mSampleRate = [asset sampleRate];
inFormat.mFormatID = kAudioFormatMPEG4AAC;
inFormat.mFormatFlags = kMPEG4Object_AAC_LC;
inFormat.mBytesPerPacket = 0;
inFormat.mFramesPerPacket = (UInt32)[asset framePerPacket];
inFormat.mBytesPerFrame = 0;
inFormat.mChannelsPerFrame = (UInt32)[asset channelCount];
inFormat.mBitsPerChannel = 0;
inFormat.mReserved = 0;
OSStatus status = AudioConverterNew(&inFormat, &outFormat, &audioConverter);
if (status != noErr) {
NSLog(#"setup converter error, status: %i\n", (int)status);
} else {
NSLog(#"Audio Converter is initialized successfully.");
}
}
typedef struct _PassthroughUserData PassthroughUserData;
struct _PassthroughUserData {
UInt32 mChannels;
UInt32 mDataSize;
const void* mData;
AudioStreamPacketDescription mPacket;
};
int inInputDataProc(AudioConverterRef aAudioConverter,
UInt32* aNumDataPackets,
AudioBufferList* aData,
AudioStreamPacketDescription** aPacketDesc,
void* aUserData)
{
PassthroughUserData* userData = (PassthroughUserData*)aUserData;
if (!userData->mDataSize) {
*aNumDataPackets = 0;
NSLog(#"inInputDataProc returns -1");
return -1;
}
if (aPacketDesc) {
userData->mPacket.mStartOffset = 0;
userData->mPacket.mVariableFramesInPacket = 0;
userData->mPacket.mDataByteSize = userData->mDataSize;
NSLog(#"mDataSize:%d", userData->mDataSize);
*aPacketDesc = &userData->mPacket;
}
aData->mBuffers[0].mNumberChannels = userData->mChannels;
aData->mBuffers[0].mDataByteSize = userData->mDataSize;
aData->mBuffers[0].mData = (void*)(userData->mData);
NSLog(#"buffer[0] - channel:%d, byte size:%u, data:%p",
aData->mBuffers[0].mNumberChannels,
(unsigned int)aData->mBuffers[0].mDataByteSize,
aData->mBuffers[0].mData);
// No more data to provide following this run.
userData->mDataSize = 0;
NSLog(#"inInputDataProc returns 0");
return 0;
}
- (void)decodeAudioFrame:(NSData *)frame withPts:(NSInteger)pts{
if(!audioConverter){
[self initAudioToolBox];
}
HCAudioAsset* asset = [self.provider getAudioAsset];
PassthroughUserData userData = { (UInt32)[asset channelCount], (UInt32)frame.length, [frame bytes]};
NSMutableData *decodedData = [NSMutableData new];
const uint32_t MAX_AUDIO_FRAMES = 128;
const uint32_t maxDecodedSamples = MAX_AUDIO_FRAMES * 1;
do {
uint8_t *buffer = (uint8_t *)malloc(maxDecodedSamples * sizeof(short int));
AudioBufferList decBuffer;
memset(&decBuffer, 0, sizeof(AudioBufferList));
decBuffer.mNumberBuffers = 1;
decBuffer.mBuffers[0].mNumberChannels = 2;
decBuffer.mBuffers[0].mDataByteSize = maxDecodedSamples * sizeof(short int);
decBuffer.mBuffers[0].mData = buffer;
UInt32 numFrames = MAX_AUDIO_FRAMES;
AudioStreamPacketDescription outPacketDescription;
memset(&outPacketDescription, 0, sizeof(AudioStreamPacketDescription));
outPacketDescription.mDataByteSize = MAX_AUDIO_FRAMES;
outPacketDescription.mStartOffset = 0;
outPacketDescription.mVariableFramesInPacket = 0;
NSLog(#"frame - size:%lu, buffer:%p", [frame length], [frame bytes]);
OSStatus rv = AudioConverterFillComplexBuffer(audioConverter,
inInputDataProc,
&userData,
&numFrames,
&decBuffer,
&outPacketDescription);
NSLog(#"num frames:%d, dec buffer [0] channels:%d, dec buffer [0] data byte size:%d, rv:%d",
numFrames, decBuffer.mBuffers[0].mNumberChannels,
decBuffer.mBuffers[0].mDataByteSize, (int)rv);
if (rv && rv != noErr) {
NSLog(#"Error decoding audio stream: %d\n", rv);
break;
}
if (numFrames) {
[decodedData appendBytes:decBuffer.mBuffers[0].mData length:decBuffer.mBuffers[0].mDataByteSize];
}
} while (true);
//void *pData = (void *)[decodedData bytes];
//audioRenderer->Render(&pData, decodedData.length, pts);
}
I've managed to decode and play H264 videos, however I'm having a difficult time with MPEG4 videos.
What CMVideoFormatDescription extensions does it need? I'm getting -8971 error (codecExtensionNotFoundErr) when trying to create a VTDecompressionSession.
This is how I create a VideoFormatDescription
OSStatus success = CMVideoFormatDescriptionCreate(kCFAllocatorDefault,
self.mediaCodec,
message.frameSize.width,
message.frameSize.height,
NULL,
&mediaDescriptor);
Instead of that NULL, I assume I need to specify a CFDictionaryRef, however I don't know what it should contain. Any idea?
After much pain and agony, I've finally managed to make it work.
I need to provide a CFDictionaryRef with at least a value for the kCMFormatDescriptionExtension_SampleDescriptionExtensionAtoms key. The value for this key also has to be a CFDictionaryRef. For H264 types this is created inside the CMVideoFormatDescriptionCreateFromH264ParameterSets and looks like this:
avcC = <014d401e ffe10016 674d401e 9a660a0f ff350101 01400000 fa000013 88010100 0468ee3c 80>
However for the MPEG4 type, you need to create this on your own. The end result should look like this:
esds = <00000000 038081e6 00000003 8081e611 00000000 00000000 058081e5 060102>
Now the way to create this is still fuzzy to me, however it somehow works. I was inspired by this link. This is the code:
- (CMFormatDescriptionRef)createFormatDescriptorFromMPEG4Message:(MessageContainer *)message {
CMVideoFormatDescriptionRef mediaDescriptor = NULL;
NSData *esdsData = [self newESDSFromData:message.frameData];
CFMutableDictionaryRef esdsDictionary = CFDictionaryCreateMutable(kCFAllocatorDefault, 1,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
CFDictionarySetValue(esdsDictionary, CFSTR("esds"), (__bridge const void *)(esdsData));
NSDictionary *dictionary = #{(__bridge NSString *)kCMFormatDescriptionExtension_SampleDescriptionExtensionAtoms : (__bridge NSDictionary *)esdsDictionary};
OSStatus status = CMVideoFormatDescriptionCreate(kCFAllocatorDefault,
self.mediaCodec,
message.frameSize.width,
message.frameSize.height,
(__bridge CFDictionaryRef)dictionary,
&mediaDescriptor);
if (status) {
NSLog(#"CMVideoFormatDesciprionCreate failed with %zd", status);
}
return mediaDescriptor;
}
- (NSData *)newESDSFromData:(NSData *)data {
NSInteger dataLength = data.length;
int full_size = 3 + 5 + 13 + 5 + dataLength + 3;
// ES_DescrTag data + DecoderConfigDescrTag + data + DecSpecificInfoTag + size + SLConfigDescriptor
int config_size = 13 + 5 + dataLength;
int padding = 12;
int8_t *esdsInfo = calloc(full_size + padding, sizeof(int8_t));
//Version
esdsInfo[0] = 0;
//Flags
esdsInfo[1] = 0;
esdsInfo[2] = 0;
esdsInfo[3] = 0;
//ES_DescrTag
esdsInfo[4] |= 0x03;
[self addMPEG4DescriptionLength:full_size
toPointer:esdsInfo + 5];
//esid
esdsInfo[8] = 0;
esdsInfo[9] = 0;
//Stream priority
esdsInfo[10] = 0;
//DecoderConfigDescrTag
esdsInfo[11] = 0x03;
[self addMPEG4DescriptionLength:config_size
toPointer:esdsInfo + 12];
//Stream Type
esdsInfo[15] = 0x11;
//Buffer Size
esdsInfo[16] = 0;
esdsInfo[17] = 0;
//Max bitrate
esdsInfo[18] = 0;
esdsInfo[19] = 0;
esdsInfo[20] = 0;
//Avg bitrate
esdsInfo[21] = 0;
esdsInfo[22] = 0;
esdsInfo[23] = 0;
//< DecSpecificInfoTag
esdsInfo[24] |= 0x05;
[self addMPEG4DescriptionLength:dataLength
toPointer:esdsInfo + 25];
//SLConfigDescrTag
esdsInfo[28] = 0x06;
//Length
esdsInfo[29] = 0x01;
esdsInfo[30] = 0x02;
NSData *esdsData = [NSData dataWithBytes:esdsInfo length:31 * sizeof(int8_t)];
free(esdsInfo);
return esdsData;
}
- (void)addMPEG4DescriptionLength:(NSInteger)length
toPointer:(int8_t *)ptr {
for (int i = 3; i >= 0; i--) {
uint8_t b = (length >> (i * 7)) & 0x7F;
if (i != 0) {
b |= 0x80;
}
ptr[3 - i] = b;
}
}
The message container is a simple wrapper around the data received from the server:
#interface MessageContainer : NSObject
#property (nonatomic) CGSize frameSize;
#property (nonatomic) NSData *frameData;
#end
Where frameSize is the size of the frame (received separately from the server) and frameData is the data itself.
I would like to extract all the bits in the following bits from NSData byte :
status Data byte : <0011...
Result turns all are 0000 0000 0000 0000 . Could you please tell me how to ?
NSData *aData = [valueData subdataWithRange:NSMakeRange(0, 2)]; //16 bit status
status= [self bitsToInt:aData];
NSString *aString = [NSString stringWithFormat:#"%d", status];
int value = [aString intValue];
NSlog(#"sadasd value : ,%d" ,value );
unsigned thbit0 = (1 << 0) & value;
unsigned thbit1 = (1 << 1) & value;
unsigned thbit2 = (1 << 2) & value;
unsigned thbit3 = (1 << 3) & value;
unsigned thbit4 = (1 << 4) & value;
unsigned thbit5 = (1 << 5) & value;
unsigned thbit6 = (1 << 6) & value;
unsigned thbit7 = (1 << 7) & value;
unsigned thbit8 = (1 << 8) & value;
unsigned thbit9 = (1 << 9) & value;
unsigned thbit10 = (1 << 10) & value;
unsigned thbit11= (1 << 11) & value;
unsigned thbit12 = (1 << 12) & value;
..
- (int) bitsToInt : (NSData *) valueDa {
uint8_t * bytePtr = (uint8_t * )[valueDa bytes];
int high = bytePtr[1] >= 0 ? bytePtr[1] : 256 + bytePtr[1];
int low = bytePtr[0] >= 0 ? bytePtr[0] : 256 + bytePtr[0];
return low | (high << 8);
}
You could try to work with bit string instead of integer values with additional bit extracting.
Here is simple decoder:
- (NSString *)getBitsFromData:(NSData *)data
{
NSMutableString *result = [NSMutableString string];
const uint8_t *bytes = [data bytes];
for (NSUInteger i = 0; i < data.length; i++)
{
uint8_t byte = bytes[i];
for (int j = 0; j < 8; j++)
{
((byte >> j) & 1) == 0 ? [result appendString:#"0"] : [result appendString:#"1"];
}
}
return result;
}
Test:
NSString *test = #"test";
NSLog(#"%#", [self getBitsFromData:[test dataUsingEncoding:NSUTF8StringEncoding]]);
Result:
2015-07-29 11:37:31.768 Test[18342:9947704] 00101110101001101100111000101110
I've to implement the RC4 encryption algorithm in my application for URL encoding.The sample part is listed below for your reference.
Actual value Before Encryption : 10/28/2013
Expected value After Encryption : ˆ!˜·hÇÔÞò
After URL encoding it should be : %0C%88%21%98%B7h%C7%D4%DE%F2
KEY USED is:#"psw"
I've tried but value after encryption & URL encoding returns in this way:
After encryption : !·hÇÔÞò
After URL encoding : %0C%C2%88%21%C2%98%C2%B7h%C3%87%C3%94%C3%9E%C3%B2
I tried converting the java code into objective c code.The java code works fine ,were as the objective c is not working, which you can see in the above result.
Here is the Java code
import java.net.URLEncoder;
public class RC4 {
private char[] key;
private int[] sbox;
private static final int SBOX_LENGTH = 256;
private static final int KEY_MIN_LENGTH = 1;
public static void main(String[] args) {
try {
RC4 rc4 = new RC4("psw");
char[] result = rc4.encrypt("10/28/2013".toCharArray());
System.out.println("encrypted string:\n"
+ new String(toByteArray(result)));
System.out.println("decrypted string:\n"
+ new String(rc4.decrypt(result)));
System.out.println("decrypted string:\n"
+ URLEncoder.encode(new String(toByteArray(result))));
} catch (InvalidKeyException e) {
System.err.println(e.getMessage());
}
}
static byte[] toByteArray(char[] chars) {
byte[] bytes = new byte[chars.length];
for (int i = 0; i < chars.length; i++) {
// bytes[i*2] = (byte) (chars[i] >> 8);
bytes[i] = (byte) chars[i];
}
return bytes;
}
public RC4(String key) throws InvalidKeyException {
setKey(key);
}
public RC4() {
}
public char[] decrypt(final char[] msg) {
return encrypt(msg);
}
public char[] encrypt(final char[] msg) {
sbox = initSBox(key);
char[] code = new char[msg.length];
int i = 0;
int j = 0;
for (int n = 0; n < msg.length; n++) {
i = (i + 1) % SBOX_LENGTH;
j = (j + sbox[i]) % SBOX_LENGTH;
swap(i, j, sbox);
int rand = sbox[(sbox[i] + sbox[j]) % SBOX_LENGTH];
code[n] = (char) (rand ^ (int) msg[n]);
}
return code;
}
private int[] initSBox(char[] key) {
int[] sbox = new int[SBOX_LENGTH];
int j = 0;
for (int i = 0; i < SBOX_LENGTH; i++) {
sbox[i] = i;
}
for (int i = 0; i < SBOX_LENGTH; i++) {
j = (j + sbox[i] + key[i % key.length]) % SBOX_LENGTH;
swap(i, j, sbox);
}
return sbox;
}
private void swap(int i, int j, int[] sbox) {
int temp = sbox[i];
sbox[i] = sbox[j];
sbox[j] = temp;
}
public void setKey(String key) throws InvalidKeyException {
if (!(key.length() >= KEY_MIN_LENGTH && key.length() < SBOX_LENGTH)) {
throw new InvalidKeyException("Key length has to be between "
+ KEY_MIN_LENGTH + " and " + (SBOX_LENGTH - 1));
}
this.key = key.toCharArray();
}
public class InvalidKeyException extends Exception {
private static final long serialVersionUID = 1L;
public InvalidKeyException(String message) {
super(message);
}
}
}
Its corresponding Objective c Code
-(NSString *)encrypt:(NSString *)string{
[self frameSBox:#"psw"];
unichar code[string.length];
const unichar* buffer = code;
int i = 0;
int j = 0;
for (int n = 0; n < string.length; n++) {
i = (i + 1) % self.SBOX_LENGTH;
j = (j + [[self.sBox objectAtIndex:i]integerValue]) % self.SBOX_LENGTH;
[self swap:i with:j];
int index=([[self.sBox objectAtIndex:i] integerValue]+[[self.sBox objectAtIndex:j] integerValue]);
int rand=([[self.sBox objectAtIndex:(index%self.SBOX_LENGTH)] integerValue]);
code[n]=(rand ^ (int)[string characterAtIndex:n]);
}
buffer = code;
return [NSString stringWithCharacters:buffer length:string.length];
}
-(NSArray *)frameSBox:(NSString *)keyValue{
if (self.sBox == nil) {
self.sBox=[[NSMutableArray alloc]init];
}
self.SBOX_LENGTH=256;
int j = 0;
for (int i = 0; i < self.SBOX_LENGTH; i++) {
[self.sBox addObject:[NSNumber numberWithInteger:i]];
}
for (int i = 0; i < self.SBOX_LENGTH; i++) {
j = (j + [[self.sBox objectAtIndex:i] integerValue] + [keyValue characterAtIndex:(i % keyValue.length)]) % self.SBOX_LENGTH;
[self swap:i with:j];
}
return self.sBox;
}
-(void)swap:(int)i with:(int)j{
id tempObj = [self.sBox objectAtIndex:i];
[self.sBox replaceObjectAtIndex:i withObject:[self.sBox objectAtIndex:j]];
[self.sBox replaceObjectAtIndex:j withObject:tempObj];
}
//I'm calling in a different class by creating the RC4encryptor object
NSString *unescaped = [[RC4StringEncryptor encryptor] encrypt:#"10/28/2013"];
logDebug(#"the value is:%#",unescaped);
NSString *escapedString = (NSString *)CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(
NULL,
(__bridge CFStringRef) unescaped,
NULL,
CFSTR("!*'();:#&=+$,/?%#[]\" "),
kCFStringEncodingUTF8));
NSLog(#"escapedString: %#",escapedString);
I've also tried
#import <CommonCrypto/CommonCryptor.h>
#implementation NSData (RC4)
- (NSData *)RC4EncryptWithKey:(NSString *)key {
char keyPtr[kCCKeySizeMinRC4+1];
bzero(keyPtr, sizeof(keyPtr));
[key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];
NSUInteger dataLength = [self length];
size_t bufferSize = dataLength + kCCKeySizeMinRC4;
void *buffer = malloc(bufferSize);
size_t numBytesEncrypted = 0;
CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmRC4, kCCModeRC4,
keyPtr, kCCKeySizeMinRC4,
NULL ,
[self bytes], dataLength,
buffer, bufferSize,
&numBytesEncrypted);
if (cryptStatus == kCCSuccess) {
return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
}
free(buffer);
return nil;
}
- (NSData*) encryptString:(NSString*)plaintext withKey:(NSString*)key {
return [[plaintext dataUsingEncoding:NSUTF8StringEncoding] RC4EncryptWithKey:key];
}
But this above code doesn't work for me.Kindly help me in this....
Somehow I fixed your code and it encrypts-decrypts perfectly. Here it is:
#interface RC4Crypt()
#property (nonatomic, strong) NSArray * key;
#property (nonatomic, strong) NSMutableArray * sBox;
#end
#implementation RC4Crypt
static const int SBOX_LENGTH = 256;
static const int KEY_MIN_LENGTH = 1;
-(NSString *)encrypt:(NSString *)string withKey:(NSString *)key{
self.sBox = [[self frameSBox:key] mutableCopy];
unichar code[string.length];
int i = 0;
int j = 0;
for (int n = 0; n < string.length; n++) {
i = (i + 1) % SBOX_LENGTH;
j = (j + [[self.sBox objectAtIndex:i]integerValue]) % SBOX_LENGTH;
[self.sBox exchangeObjectAtIndex:i withObjectAtIndex:j];
int index=([self.sBox[i] integerValue]+[self.sBox[j] integerValue]);
int rand=([self.sBox[(index%SBOX_LENGTH)] integerValue]);
code[n]=(rand ^ (int)[string characterAtIndex:n]);
}
const unichar* buffer;
buffer = code;
return [NSString stringWithCharacters:buffer length:string.length];
}
- (NSString*) decrypt:(NSString*)string withKey:(NSString*)key
{
return [self encrypt:string withKey:key];
}
-(NSArray *)frameSBox:(NSString *)keyValue{
NSMutableArray *sBox = [[NSMutableArray alloc] initWithCapacity:SBOX_LENGTH];
int j = 0;
for (int i = 0; i < SBOX_LENGTH; i++) {
[sBox addObject:[NSNumber numberWithInteger:i]];
}
for (int i = 0; i < SBOX_LENGTH; i++) {
j = (j + [sBox[i] integerValue] + [keyValue characterAtIndex:(i % keyValue.length)]) % SBOX_LENGTH;
[sBox exchangeObjectAtIndex:i withObjectAtIndex:j];
}
return [NSArray arrayWithArray:sBox];
}
#end
How to Verify digital signature with public key in iOS without using any third party code(e.g.) open SSL?
I need to verify Digital signature in iOS App with a public key. Can some one help me how to achieve that without using third party software.
I am trying below code but the problem is I don't have certificate in my App so can not create SecTrustRef.
CODE:
NSString *certPath = [[NSBundle mainBundle] pathForResource:#"yyy"
ofType:#"xxx"];
SecCertificateRef myCertificate = nil;
NSData *certificateData = [[NSData alloc] initWithContentsOfFile :certPath];
myCertificate = SecCertificateCreateWithData(kCFAllocatorDefault, (__bridge CFDataRef)certificateData);
SecPolicyRef myPolicy = SecPolicyCreateBasicX509();
SecTrustRef trustRef;
SecTrustCreateWithCertificates(myCertificate, myPolicy, &trustRef);
SecKeyRef keyRef = SecTrustCopyPublicKey (trustRef);
BOOL status = SecKeyRawVerify (keyRef,
kSecPaddingPKCS1SHA1,
(const uint8_t *)[data bytes],
(size_t)[data length],
(const uint8_t *)[signature bytes],
(size_t)[signature length]
);
I have the following:
Public Key (NSString*)
Signature (NSString*)
Data (NSString*)
Please help me what all option I have in iOS SDK if I don't want to use ant third party open source.
You can package your public key in a X509 certificate to use the iOS built in functions easily, using openSSL:
openssl req -x509 -out public_key.pem -outform pem -new -newkey rsa:2048 -keyout private_key.pem
the PEM format is base64 encoded, you can switch the -outform to DER to get binary file.
you can import the PEM format by adding a const NSString to your program and adding category to NSData with this function:
- (id) initWithBase64EncodedString:(NSString *) string {
NSMutableData *mutableData = nil;
if( string ) {
unsigned long ixtext = 0;
unsigned long lentext = 0;
unsigned char ch = 0;
unsigned char inbuf[4], outbuf[3]; // buffer sizes fixed by AOL LLC
short i = 0, ixinbuf = 0;
BOOL flignore = NO;
BOOL flendtext = NO;
NSData *base64Data = nil;
const unsigned char *base64Bytes = nil;
// Convert the string to ASCII data.
base64Data = [string dataUsingEncoding:NSASCIIStringEncoding];
base64Bytes = [base64Data bytes];
mutableData = [NSMutableData dataWithCapacity:[base64Data length]];
lentext = [base64Data length];
while( YES ) {
if( ixtext >= lentext ) break;
ch = base64Bytes[ixtext++];
flignore = NO;
if( ( ch >= 'A' ) && ( ch <= 'Z' ) ) ch = ch - 'A';
else if( ( ch >= 'a' ) && ( ch <= 'z' ) ) ch = ch - 'a' + 26;
else if( ( ch >= '0' ) && ( ch <= '9' ) ) ch = ch - '0' + 52;
else if( ch == '+' ) ch = 62;
else if( ch == '=' ) flendtext = YES;
else if( ch == '/' ) ch = 63;
else flignore = YES;
if( ! flignore ) {
short ctcharsinbuf = 3;
BOOL flbreak = NO;
if( flendtext ) {
if( ! ixinbuf ) break;
if( ( ixinbuf == 1 ) || ( ixinbuf == 2 ) ) ctcharsinbuf = 1;
else ctcharsinbuf = 2;
ixinbuf = 3;
flbreak = YES;
}
inbuf [ixinbuf++] = ch;
if( ixinbuf == 4 ) {
ixinbuf = 0;
outbuf [0] = ( inbuf[0] << 2 ) | ( ( inbuf[1] & 0x30) >> 4 );
outbuf [1] = ( ( inbuf[1] & 0x0F ) << 4 ) | ( ( inbuf[2] & 0x3C ) >> 2 );
outbuf [2] = ( ( inbuf[2] & 0x03 ) << 6 ) | ( inbuf[3] & 0x3F );
for( i = 0; i < ctcharsinbuf; i++ )
[mutableData appendBytes:&outbuf[i] length:1];
}
if( flbreak ) break;
}
}
}
self = [self initWithData:mutableData];
return self;
}
ofcourse you pull this file into the certificateData
if you want to use your existing public key just pull it out and write it in a X509 cert format using openSSL
$ openssl rsa -in id_rsa -out pub.der -outform DER -pubout
good luck
If your key data is packaged as PKCS12 data, use SecPKCS12Import to import it and use the public key.
You need to pass a digest (hash) of your data to the verification function. See iOS: Verifying a File With a Certificate and Signature - Public Key is Wrong, Verification Fails
#interface HDSecurityPolicy :AFSecurityPolicy
#end
#implementation HDSecurityPolicy
///pem formate(base64) -> NSData
- (void)setPinnedCertificates:(NSSet *)pinnedCertificates {
[super setPinnedCertificates:pinnedCertificates];
if (self.pinnedCertificates) {
NSMutableSet *mutablePinnedPublicKeys = [NSMutableSet setWithCapacity:[self.pinnedCertificates count]];
for (NSData *pubCertificate in self.pinnedCertificates) {
id publicKey = [HDSecurityPolicy publicSecKeyFromKeyBits:pubCertificate];
if (!publicKey) {
continue;
}
[mutablePinnedPublicKeys addObject:publicKey];
}
[self setValue:mutablePinnedPublicKeys forKey:#"pinnedPublicKeys"];
}
}
// 从公钥证书文件中获取到公钥的SecKeyRef指针
+ (id)publicSecKeyFromKeyBits:(NSData *)givenData {
NSMutableDictionary *options = [NSMutableDictionary dictionary];
options[(__bridge id)kSecAttrKeyType] = (__bridge id) kSecAttrKeyTypeRSA;
options[(__bridge id)kSecAttrKeyClass] = (__bridge id) kSecAttrKeyClassPublic;
NSError *error = nil;
CFErrorRef ee = (__bridge CFErrorRef)error;
////'SecKeyCreateWithData' is only available on iOS 10.0 or newer
id ret = (__bridge_transfer id)SecKeyCreateWithData((__bridge CFDataRef)givenData, (__bridge CFDictionaryRef)options, &ee);
if (error) {
return nil;
}
return ret;
}
#end