【问题标题】:Swift RC4 vs. Objective-C RC4 PerformanceSwift RC4 与 Objective-C RC4 性能对比
【发布时间】:2015-02-09 08:44:28
【问题描述】:

我一直在尝试将 Rc4 算法从 Objective-c 重写为 swift,以测试 apples(现已旧)声称它运行得更快。 但是,在这些时候,我一定是在某个地方做错了什么

这是目标c代码:

+(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;
}

使用 -O3 编译时运行速度非常快,我得到了以下时间:

100 次运行:0.006 秒

带密钥:6f7e2a3d744a3b5859725f412f (128bit)

并输入:“MySecretCodeToBeEncryptionSoNobodySeesIt”

这是我尝试使用 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;
}

我已经尝试实现它,使它看起来尽可能像objective-c 版本。 然而,这给了我这些可怕的时刻,使用 -O

100 次运行:0.5 秒

编辑 代码现在应该使用我发布的扩展方法在 xcode 6.1 中运行。

我像这样从终端运行它:

xcrun swiftc -O Swift.swift -o swift

Swift.swift 是我的文件,swift 是我的可执行文件

【问题讨论】:

  • 您的 Swift 代码未在 Xcode 6.1 中构建。
  • 在任何一种情况下都不要在实际加密部分中使用字符串。加密是一种数据操作。将您的结果与 Common Crypto 进行比较,您应该会发现这两种实现都不是很接近。
  • 这里的目的是在 Objective-c 和 swift 中测试非常相似的代码片段,我以为我正在这样做,但是这些奇怪的运行时正在反对它。这与优化加密的安全性甚至是正确的无关。不过,感谢您的输入,如果看起来很奇怪,请见谅。
  • Swift 中的字符串可能非常慢,因为由于更好的 unicode 处理,没有直接索引到它们。添加到 String 的扩展不是一个好主意,它们不适用于需要多个 UTF-16 代码单元的 unicode 字符,例如表情符号,这就是为什么它们不是 Swift 的一部分。由于扩展不适用于所有字符串字符,因此只需将方法设为私有即可。还要检查 Swift 编译优化级别。
  • 我实际上一直在寻找有关编译优化级别的文档 (stackoverflow.com/questions/27233479/…) 据我所知 -O (swift) 类似于 -O3 (objective-c) 但我没有能够找到任何严格的文档来支持这一点。再次感谢!

标签: objective-c swift performance encryption microbenchmark


【解决方案1】:

通常声称速度并不真正适用于加密算法,它们更多地适用于我通常所说的“业务逻辑”。位、字节、16/32/64 位字等功能通常难以优化。基本上,加密算法被设计为对这些数据结构进行密集操作,可以优化的选择相对较少。

以 Java 为例。尽管比大多数解释语言快得多,但它确实无法与 C/C++ 相比,更不用说汇编优化的加密算法了。大多数相对较小的代数问题也是如此。

为了让事情变得更快,您至少应该使用explicit numeric types 作为您的号码。

【讨论】:

  • 确实是“业务逻辑”。我正在尝试一些基准测试,因为苹果声称与 Objective-c 相比,Rc4 加密的速度显着提高(对我来说,python 不太有趣)。这篇文章提到了 wwdc (theregister.co.uk/2014/06/02/…) 上关于基准测试的内容
【解决方案2】:

在对代码进行过度测试后,我将其范围缩小到使我的时间变得异常缓慢的原因。 如果我注释掉这段代码,那么 iK 数组就只包含它的初始值。我从 5 秒的运行时间缩短到 1 秒。这是一个显着的增长。

for var i = 0; i < 256 ; i++ {
var c = key[i%keyLength]
iK[i] = c;  
}

问题出在这部分:

var c = key[i%keyLength]

在 Swift 中没有“characterAtIndex(int)”方法,因此我这样做是为了获得 characterAtIndex。我使用我的扩展来做到这一点:

extension String {
  subscript (i: Int) -> String {
    return String(Array(self)[i])
  }
}

但本质上是一样的:

var c = Array(key)[i%keyLength]

我们得到了 O(n) 的运行时间,而不是 Objective-c 中此操作的 O(1) -(恒定时间)。

【讨论】:

  • 键根本不应该是字符串。所以我认为苹果不会为此烦恼。我认为仍然有很多优化可能,但苹果再次创建了自己的封闭式开发。环境,我无法测试。
  • @Christian 一般来说,unicode 不能直接索引,因为某些字符可以由多个代码单元组成,无论是 UTF-8、UTF-16 还是 UTF-32 编码。美国国旗符号??由四个 UTF-16 编码单元组成:0xD83C 0xDDFA、0xD83C 0xDDF8。大多数表情符号是两个 UTF-16 代码单元。 UTF-16 是StringNSString 使用的底层编码。正如 owlstead 和我所指出的,加密是一种数据操作,而不是字符。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多