I have been trying to rewrite a Rc4-algorithm from objective-c to swift, to test out apples(now old) claims, about it running a lot faster. However there must be somewhere that I am doing something horribly wrong with these times I am getting
This is the objective c code:
+(NSString*)Rc4:(NSString*)aInput key:(NSString *)aKey {
NSMutableArray *iS = [[NSMutableArray alloc] initWithCapacity:256];
NSMutableArray *iK = [[NSMutableArray alloc] initWithCapacity:256];
for (int i = 0; i <256;i++){
[iS addObject:[NSNumber numberWithInt:i]];
}
for(short i=0;i<256;i++){
UniChar c = [aKey characterAtIndex:i%aKey.length];
[iK addObject:[NSNumber numberWithChar:c]];
}
int j=2;
for (int i=0; i<255;i++){
int is = [[iS objectAtIndex:i] intValue];
UniChar ik = (UniChar)[[iK objectAtIndex:i]charValue];
j= (j+is+ik)%256;
NSNumber *temp = [iS objectAtIndex:i];
[iS replaceObjectAtIndex:i withObject:[iS objectAtIndex:j]];
[iS replaceObjectAtIndex:j withObject:temp];
}
int i =0;
j=0;
NSString *result = aInput;
for (short x=0;x<[aInput length]; x++){
i = (i+1)%256;
int is = [[iS objectAtIndex:i]intValue];
j=(j+is)%256;
int is_i = [[iS objectAtIndex:i]intValue];
int is_j = [[iS objectAtIndex:j]intValue];
int t= (is_i+is_j)%256;
int iY = [[iS objectAtIndex:t]intValue];
UniChar ch = (UniChar)[aInput characterAtIndex:x];
UniChar ch_y=ch^iY;
//NSLog(ch);
//NSLog(iY);
result = [result stringByReplacingCharactersInRange:NSMakeRange(x,1) withString:
[NSString stringWithCharacters:&ch_y length:1] ];
}
[iS release];
[iK release];
return result;
}
This runs pretty fast compiling with -O3 I get times of:
100 runs:0.006 seconds
With key: 6f7e2a3d744a3b5859725f412f (128bit)
and input: "MySecretCodeToBeEncryptionSoNobodySeesIt"
This is my attempt to implement it in the same way using Swift:
extension String {
subscript (i: Int) -> String {
return String(Array(self)[i])
}
}
extension Character {
func unicodeValue() -> UInt32 {
for s in String(self).unicodeScalars {
return s.value
}
return 0
}
}
func Rc4(input:String, key:String)-> String{
var iS = Array(count:256, repeatedValue: 0)
var iK = Array(count:256, repeatedValue: "")
var keyLength = countElements(key)
for var i = 0; i < 256; i++ {
iS[i] = i;
}
for var i = 0; i < 256 ; i++ {
var c = key[i%keyLength]
iK[i] = c;
}
var j = 2
for var i = 0; i < 255; i++ {
var iss = iS[i]
var ik = iK[i]
// transform string to int
var ik_x:Character = Character(ik)
var ikk_xx = Int(ik_x.unicodeValue())
j = (j+iss+ikk_xx)%256;
var temp = iS[i]
iS[i] = iS[j]
iS[j] = temp
}
var i = 0
j=0
var result = input
var eles = countElements(input)
for var x = 0 ; x<eles ; x++ {
i = (i+1)%256
var iss = iS[i]
j = (j+iss)%256
var is_i = iS[i]
var is_j = iS[j]
var t = (is_i+is_j)%256
var iY = iS[t]
var ch = (input[x])
var ch_x:Character = Character(ch)
var ch_xx = Int(ch_x.unicodeValue())
var ch_y = ch_xx^iY
var start = advance(result.startIndex, x)
var end = advance(start,1);
let range = Range(start:start, end:end)
var maybestring = String(UnicodeScalar(ch_y))
result = result.stringByReplacingCharactersInRange(range, withString:maybestring)
}
return result;
}
I have tried to implement it so it looks as much as the objective-c version as possible. This however gives me these horrible times, using -O
100 runs: 0.5 seconds
EDIT Code should now run in xcode 6.1 using the extension methods I posted.
I run it from terminal like this:
xcrun swiftc -O Swift.swift -o swift
where Swift.swift is my file, and swift is my executable
Usually claims of speed don't really apply to encryption algorithms, they are more for what I usually call "business logic". The functions on bits, bytes, 16/32/64 bit words etc. are usually difficult to optimize. Basically encryption algorithms are designed to be dense operations on these data structures with relatively few choices that can be optimized away.
Take for instance Java. Although infinitely faster than most interpreted languages it really doesn't compare well with C/C++, let alone with assembly optimized encryption algorithms. The same goes for most relatively small algebraic problems.
To make things faster you should at least use explicit numeric types for your numbers.