移植在 PHP 中实现的 XOR 加密方案


Porting XOR encryption scheme implemented in PHP

不幸的是,我无法理解php代码,但我需要将这个php代码转换为Objective-C。可能谁知道其他人在目标 C 中进行异或加密的方式?

我需要这是结果加密:

key: kbyz5eH64z
string: {"date":"01.01.2014 00:00:00","value":5}
encrypted: rDi66Mfqu9y8kvs%2F3Fc%2Fg%2BX5N%2FPtARgPDP7Gk7lLvOxUFNyglxogVA%3D%3D
decrypted: {"date":"01'�Mi�����q�=���e� #~�E�����i�11

我发现的PHP代码:

function strcode($str, $passw="")
{
   $salt = "Dn8*#2n!9j";
   $len = strlen($str);
   $gamma = '';
   $n = $len>100 ? 8 : 2;
   while( strlen($gamma)<$len )
   {
      $gamma .= substr(pack('H*', sha1($passw.$gamma.$salt)), 0, $n);
   }
   return $str^$gamma;
}
$txt = "Hello XOR encode!";
$txt = base64_encode(strcode($txt, 'mypassword'));
echo $txt;
/* result - ZOHdWKf+cf7vAwpJNfSJ8s8= */
$txt = "ZOHdWKf+cf7vAwpJNfSJ8s8=";
$txt = strcode(base64_decode($txt), 'mypassword');
echo $txt;
/* result - Hello XOR encode! */

尝试使用此代码,但它不适用于我的示例,因为加密字符串与示例不同(rDi66Mfqu9y8kvs%2F3Fc%2Fg%2BX5N%2FPtARgPDP7Gk7lLvOxUFNyglxogVA%3D%3D):

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    NSString *filePath = [[NSBundle mainBundle] pathForResource:@"document" ofType:@"json"];
    NSData *content = [[NSData alloc] initWithContentsOfFile:filePath];
    NSString* jsonString = [[NSString alloc] initWithData:content encoding:NSUTF8StringEncoding];
    NSLog(@"Input string:%@", jsonString);
    NSString *obfuscatedStr = [[self obfuscate:jsonString withKey:@"kbyz5eH64z"] base64EncodedStringWithOptions:0];
    NSLog(@"Obfuscated string:%@", obfuscatedStr);
    return YES;
}
- (NSData *)obfuscate:(NSString *)string withKey:(NSString *)key
{
    // Create data object from the string
    NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];
    // Get pointer to data to obfuscate
    char *dataPtr = (char *) [data bytes];
    // Get pointer to key data
    char *keyData = (char *) [[key dataUsingEncoding:NSUTF8StringEncoding] bytes];
    // Points to each char in sequence in the key
    char *keyPtr = keyData;
    int keyIndex = 0;
    // For each character in data, xor with current value in key
    for (int x = 0; x < [data length]; x++)
    {
        // Replace current character in data with
        // current character xor'd with current key value.
        // Bump each pointer to the next character
        *dataPtr = *dataPtr ^ *keyPtr;
        dataPtr++;
        keyPtr++;
        // If at end of key data, reset count and
        // set key pointer back to start of key value
        if (++keyIndex == [key length])
            keyIndex = 0, keyPtr = keyData;
    }
    return [[NSData alloc] initWithData:data];
}

您需要实现创建$gamma的方法。然后要编码或解码,请创建$gamma并使用输入进行异或。

注意:使用自制加密从来都不是一个好主意,它总是存在缺陷,而是使用标准 AES。

由于这是加密,因此您必须获得应用程序的导出权限,这对于自行开发的算法来说可能相当困难。您将需要美国出口许可,因为分发该应用程序的是Apple。

这是示例代码,它可能更好,但它有效:

@interface Test : NSObject
- (NSData *)strcodeData:(NSData *)data password:(NSString *)password;
@end
@implementation Test
- (NSData *)strcodeData:(NSData *)data password:(NSString *)password {
    NSString *gamma = [self gammaWithPassword:password length:data.length];
    NSData *gammaData = [gamma dataUsingEncoding:NSMacOSRomanStringEncoding];
    NSData *encryptedData = [self xorData:data withString:gammaData];
    return encryptedData;
}
- (NSString *)gammaWithPassword:(NSString *)password length:(unsigned long)length {
    NSString *salt = @"Dn8*#2n!9j";
    NSMutableString *gamma = [NSMutableString new];
    int chunkSize = length>100 ? 8 : 2;
    NSMutableString *shaFodder = [NSMutableString new];
    while( gamma.length < length) {
        shaFodder = [NSMutableString stringWithFormat:@"%@%@%@", password, gamma, salt];
        NSString *shaStringOut =  [self sha1WithString:shaFodder];
        [gamma appendString:[shaStringOut substringToIndex:chunkSize]];
    }
    return gamma;
}
- (NSData *)xorData:(NSData *)d1 withString:(NSData *)d2 {
    if (d2.length < d1.length) {
        return nil;
    }
    NSMutableData *dm1 = [d1 mutableCopy];
    uint8_t *b1 = dm1.mutableBytes;
    const uint8_t *b2 = d2.bytes;
    for (int i=0; i<d1.length; i++) {
        b1[i] ^= b2[i];
    }
    return dm1;
}
- (NSString *)sha1WithString:(NSString *)string {
    NSData *shaDataIn = [string dataUsingEncoding:NSMacOSRomanStringEncoding];
    NSData *shaDataOut = [self doSha1:shaDataIn];
    NSString *shaStringOut = [[NSString alloc] initWithData:shaDataOut encoding:NSMacOSRomanStringEncoding];
    return shaStringOut;
}
- (NSData *)doSha1:(NSData *)dataIn
{
    NSMutableData *macOut = [NSMutableData dataWithLength:CC_SHA1_DIGEST_LENGTH];
    CC_SHA1( dataIn.bytes,
              (const uint8_t)dataIn.length,
              macOut.mutableBytes);
    return macOut;
}
@end

测试:

Test *test = [Test new];
// Note: NSMacOSRomanStringEncoding is used because it is a true 8-bit encoding
NSString *password = @"mypassword";
NSString *text = @"Hello XOR encode!";
NSLog(@"text:          %@", text);
// encode
NSData *data = [text dataUsingEncoding:NSMacOSRomanStringEncoding];
NSData *encodedData = [test strcodeData:data password:(NSString *)password];
NSString *encodedBase64 = [encodedData base64EncodedStringWithOptions:0];
NSLog(@"encodedBase64: %@", encodedBase64);
NSLog(@"expected:      ZOHdWKf+cf7vAwpJNfSJ8s8=");
// decode
NSData *encodedEncryptedData = [[NSData alloc] initWithBase64EncodedString:encodedBase64 options:0];
NSData *encryptedData = [test strcodeData:encodedEncryptedData password:password];
NSString *decoded = [[NSString alloc] initWithData:encryptedData encoding:NSMacOSRomanStringEncoding];
NSLog(@"decoded:       %@", decoded);

输出:

文本:你好异或编码! encodedBase64: ZOHdWKf+cf7vAwpJNfSJ8s8= 预期: ZOHdWKf+cf7vAwpJNfSJ8s8= 解码:你好异或编码! 

您尝试翻译的 PHP 代码没有实现您在 Objective-C 代码中实现的那种简单的 XOR 编码。它使用一种相当奇怪的方案(基于 SHA1)来生成一个针对输入的异或非重复焊盘。

Objective-C代码的PHP等效项很简单:

function strcode($str, $passwd) {
    return $str ^ str_repeat($passwd, ceil(strlen($str) / strlen($passwd)));
}

实现与当前PHP代码等效的代码会更加困难。您可以使用 CC_SHA1 来计算 SHA1 哈希,但请注意,它的调用约定比 PHP 中的调用约定要多一点。