objective-c实现authCode 解决php与ios通信加密的问题

PHP 代码如下:

<?php
/**
 * 加密解密 字符串
 * @param string $string 原字符串
 * @param string  $auth_key 加密的KEY
 * @param string $operation  加密解密的开关   ENCODE:加密, DECODE:解密
 * @return string|mixed
 */
function authCode($string, $auth_key, $operation='ENCODE') {
	$key = md5($auth_key);
	$key_length = strlen($key);

	//base64_decode 默认是 iso-8859-1 转 UTF-8 用 utf8_decode(base64_decode($string))
	$string = $operation == 'DECODE' ? utf8_decode(base64_decode($string)) : substr(md5($string.$key), 0, 8).$string;
	$string_length = strlen($string);

	$rndkey = $box = array();
	$result = '';

	for($i = 0; $i <= 255; $i++) {
		$rndkey[$i] = ord($key[$i % $key_length]);
		$box[$i] = $i;
	} 
 
	for($j = $i = 0; $i < 256; $i++) {
		$j = ($j + $box[$i] + $rndkey[$i]) % 256;
		$tmp = $box[$i];
		$box[$i] = $box[$j];
		$box[$j] = $tmp;
	}

	for($a = $j = $i = 0; $i < $string_length; $i++) {
		$a = ($a + 1) % 256;
		$j = ($j + $box[$a]) % 256;
		$tmp = $box[$a];
		$box[$a] = $box[$j];
		$box[$j] = $tmp;
		$result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
	}

	if($operation == 'DECODE') {
		if(substr($result, 0, 8) == substr(md5(substr($result, 8).$key), 0, 8)) {
			return substr($result, 8);
		} else {
			return '';
		}
	} else {
		//base64_encode 默认是 iso-8859-1 转 UTF-8 用 base64_encode(utf8_encode($result))
		return str_replace('=', '',base64_encode(utf8_encode($result)));
	}
}

$key = "123";
$string = "test";
$a = authCode($string, $key);
var_dump($a);
var_dump(authCode($a, $key,'DECODE'));
?>



objective-c 代码如下:

//
//  Base64.h
//  Base64
//
//  Created by wangzhongbin on 13-7-5.
//  Copyright (c) 2013年 iOS Group. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface NSData (Base64)

+ (NSData *)dataWithBase64EncodedString:(NSString *)string;
- (NSString *)base64EncodedStringWithWrapWidth:(NSUInteger)wrapWidth;
- (NSString *)base64EncodedString;

@end


@interface NSString (Base64)

+ (NSString *)stringWithBase64EncodedString:(NSString *)string encoding:(NSStringEncoding)encoding;
+ (NSString *)stringWithBase64EncodedString:(NSString *)string;
- (NSString *)base64EncodedStringWithWrapWidth:(NSUInteger)wrapWidth;
- (NSString *)base64EncodedString:(NSStringEncoding)encoding;
- (NSString *)base64EncodedString;
- (NSString *)base64DecodedString:(NSStringEncoding)encoding;
- (NSString *)base64DecodedString;
- (NSData *)base64DecodedData;

- (NSString *)authCodeEncoded:(NSString *)key encoding:(NSStringEncoding)encoding;
- (NSString *)authCodeEncoded:(NSString *)key;
- (NSString *)authCodeDecoded:(NSString *)key encoding:(NSStringEncoding)encoding;
- (NSString *)authCodeDecoded:(NSString *)key;
@end


//
//  Base64.m
//  Base64
//
//  Created by wangzhongbin on 13-7-5.
//  Copyright (c) 2013年 iOS Group. All rights reserved.
//

#import "Base64.h"
#import <CommonCrypto/CommonDigest.h>

#import <Availability.h>
#if !__has_feature(objc_arc)
#error This library requires automatic reference counting
#endif

typedef enum {
	NSStringAuthCodeEncoded,
	NSStringAuthCodeDecoded
} NSStringAuthCode;


@implementation NSData (Base64)

+ (NSData *)dataWithBase64EncodedString:(NSString *)string
{
    const char lookup[] =
    {
        99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 
        99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 
        99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 62, 99, 99, 99, 63, 
        52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 99, 99, 99, 99, 99, 99, 
        99,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 
        15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 99, 99, 99, 99, 99, 
        99, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 
        41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 99, 99, 99, 99, 99
    };
    
    NSData *inputData = [string dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
    long long inputLength = [inputData length];
    const unsigned char *inputBytes = [inputData bytes];
    
    long long maxOutputLength = (inputLength / 4 + 1) * 3;
    NSMutableData *outputData = [NSMutableData dataWithLength:maxOutputLength];
    unsigned char *outputBytes = (unsigned char *)[outputData mutableBytes];

    int accumulator = 0;
    long long outputLength = 0;
    unsigned char accumulated[] = {0, 0, 0, 0};
    for (long long i = 0; i < inputLength; i++)
    {
        unsigned char decoded = lookup[inputBytes[i] & 0x7F];
        if (decoded != 99)
        {
            accumulated[accumulator] = decoded;
            if (accumulator == 3)
            {
                outputBytes[outputLength++] = (accumulated[0] << 2) | (accumulated[1] >> 4);  
                outputBytes[outputLength++] = (accumulated[1] << 4) | (accumulated[2] >> 2);  
                outputBytes[outputLength++] = (accumulated[2] << 6) | accumulated[3];
            }
            accumulator = (accumulator + 1) % 4;
        }
    }
    
    //handle left-over data
    if (accumulator > 0) outputBytes[outputLength] = (accumulated[0] << 2) | (accumulated[1] >> 4);
    if (accumulator > 1) outputBytes[++outputLength] = (accumulated[1] << 4) | (accumulated[2] >> 2);
    if (accumulator > 2) outputLength++;
    
    //truncate data to match actual output length
    outputData.length = outputLength;
    return outputLength? outputData: nil;
}

- (NSString *)base64EncodedStringWithWrapWidth:(NSUInteger)wrapWidth
{
    //ensure wrapWidth is a multiple of 4
    wrapWidth = (wrapWidth / 4) * 4;
    
    const char lookup[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
    
    long long inputLength = [self length];
    const unsigned char *inputBytes = [self bytes];
    
    long long maxOutputLength = (inputLength / 3 + 1) * 4;
    maxOutputLength += wrapWidth? (maxOutputLength / wrapWidth) * 2: 0;
    unsigned char *outputBytes = (unsigned char *)malloc(maxOutputLength);
    
    long long i;
    long long outputLength = 0;
    for (i = 0; i < inputLength - 2; i += 3)
    {
        outputBytes[outputLength++] = lookup[(inputBytes[i] & 0xFC) >> 2];
        outputBytes[outputLength++] = lookup[((inputBytes[i] & 0x03) << 4) | ((inputBytes[i + 1] & 0xF0) >> 4)];
        outputBytes[outputLength++] = lookup[((inputBytes[i + 1] & 0x0F) << 2) | ((inputBytes[i + 2] & 0xC0) >> 6)];
        outputBytes[outputLength++] = lookup[inputBytes[i + 2] & 0x3F];
        
        //add line break
        if (wrapWidth && (outputLength + 2) % (wrapWidth + 2) == 0)
        {
            outputBytes[outputLength++] = '\r';
            outputBytes[outputLength++] = '\n';
        }
    }
    
    //handle left-over data
    if (i == inputLength - 2)
    {
        // = terminator
        outputBytes[outputLength++] = lookup[(inputBytes[i] & 0xFC) >> 2];
        outputBytes[outputLength++] = lookup[((inputBytes[i] & 0x03) << 4) | ((inputBytes[i + 1] & 0xF0) >> 4)];
        outputBytes[outputLength++] = lookup[(inputBytes[i + 1] & 0x0F) << 2];
        outputBytes[outputLength++] =   '=';
    }
    else if (i == inputLength - 1)
    {
        // == terminator
        outputBytes[outputLength++] = lookup[(inputBytes[i] & 0xFC) >> 2];
        outputBytes[outputLength++] = lookup[(inputBytes[i] & 0x03) << 4];
        outputBytes[outputLength++] = '=';
        outputBytes[outputLength++] = '=';
    }
    
    if (outputLength >= 4)
    {
        //truncate data to match actual output length
        outputBytes = realloc(outputBytes, outputLength);
        return [[NSString alloc] initWithBytesNoCopy:outputBytes
                                              length:outputLength
                                            encoding:NSASCIIStringEncoding
                                        freeWhenDone:YES];
    }
    else if (outputBytes)
    {
        free(outputBytes);
    }
    return nil;
}

- (NSString *)base64EncodedString
{
    return [self base64EncodedStringWithWrapWidth:0];
}

@end


@implementation NSString (Base64)

+ (NSString *)stringWithBase64EncodedString:(NSString *)string encoding:(NSStringEncoding)encoding
{
    NSData *data = [NSData dataWithBase64EncodedString:string];
    if (data)
    {
        return [[self alloc] initWithData:data encoding:encoding];
    }
    return nil;
}

+ (NSString *)stringWithBase64EncodedString:(NSString *)string
{
    return [self stringWithBase64EncodedString:string encoding:NSUTF8StringEncoding];
}

- (NSString *)base64EncodedStringWithWrapWidth:(NSUInteger)wrapWidth
{
    NSData *data = [self dataUsingEncoding:NSUTF8StringEncoding allowLossyConversion:YES];
    return [data base64EncodedStringWithWrapWidth:wrapWidth];
}

- (NSString *)base64EncodedString:(NSStringEncoding)encoding
{
    NSData *data = [self dataUsingEncoding:encoding allowLossyConversion:YES];
    return [data base64EncodedString];
}

- (NSString *)base64EncodedString
{
    return [self base64EncodedString:NSUTF8StringEncoding];
}

- (NSString *)base64DecodedString:(NSStringEncoding)encoding
{
    return [NSString stringWithBase64EncodedString:self encoding:encoding];
}

- (NSString *)base64DecodedString
{
    return [NSString stringWithBase64EncodedString:self];
}

- (NSData *)base64DecodedData
{
    return [NSData dataWithBase64EncodedString:self];
}

- (NSString *)md5 {
    const char *concat_str = [self UTF8String];
    unsigned char result[CC_MD5_DIGEST_LENGTH];
    CC_MD5(concat_str, strlen(concat_str), result);
    NSMutableString *hash = [NSMutableString string];
    for (int i = 0; i < 16; i++)
        [hash appendFormat:@"%02x", result[i]];
    return [hash lowercaseString];
}

- (NSString *)authCode:(NSString *)auth_key operation:(NSStringAuthCode)operation encoding:(NSStringEncoding)encoding;
{
    NSMutableArray *rndkey = [NSMutableArray array];
    NSMutableArray *box = [NSMutableArray array];
    NSMutableString *result = [NSMutableString string];
    
    NSString *key = [auth_key md5];
    NSUInteger key_length = key.length;
    NSString *string = (operation == NSStringAuthCodeDecoded) ? [self base64DecodedString:encoding] : [NSString stringWithFormat:@"%@%@",[[[NSString stringWithFormat:@"%@%@",self,key] md5] substringToIndex:8],self];
    NSUInteger string_length = string.length;
    
    for(int i = 0; i <= 255; i++) {
        [rndkey addObject:[NSNumber numberWithUnsignedShort:[key characterAtIndex:i%key_length]]];
        [box addObject:[NSNumber numberWithUnsignedShort:i]];
    }
    
    int j = 0;
    for(int i = 0; i < 256; i++) {
        unsigned short b = [[box objectAtIndex:i] unsignedShortValue];
        unsigned short r = [[rndkey objectAtIndex:i] unsignedShortValue];
        j = (j + b + r) % 256;
        [box replaceObjectAtIndex:i withObject:[box objectAtIndex:j]];
        [box replaceObjectAtIndex:j withObject:[NSNumber numberWithUnsignedShort:b]];
    }
    
    int a = 0;
    j = 0;
    for(int i = 0; i < string_length; i++) {
        a = (a + 1) % 256;
        unsigned short b = [[box objectAtIndex:a] unsignedShortValue];
        j = (j + b) % 256;
        [box replaceObjectAtIndex:a withObject:[box objectAtIndex:j]];
        [box replaceObjectAtIndex:j withObject:[NSNumber numberWithUnsignedShort:b]];
        
        unsigned short sc = [string characterAtIndex:i];
        unsigned short bi = [[box objectAtIndex:(([[box objectAtIndex:a] unsignedShortValue] + [[box objectAtIndex:j] unsignedShortValue]) % 256)] unsignedShortValue];
        unsigned short k = sc ^ bi;
        [result appendFormat:@"%C",k];
    }
    
    if(operation == NSStringAuthCodeDecoded) {
        NSString *start = [result substringToIndex:8];
        NSString *end = [[[NSString stringWithFormat:@"%@%@",[result substringFromIndex:8],key] md5]  substringToIndex:8];
        if([start isEqualToString:end]){
            return [result substringFromIndex:8];
        }
        else{
            return nil;
        }
    } else {
        return [[result base64EncodedString:encoding] stringByReplacingOccurrencesOfString:@"=" withString:@""];
    }
}

- (NSString *)authCodeEncoded:(NSString *)key encoding:(NSStringEncoding)encoding
{
    return [self authCode:key operation:NSStringAuthCodeEncoded encoding:encoding];
}

- (NSString *)authCodeEncoded:(NSString *)key
{
    return [self authCodeEncoded:key encoding:NSUTF8StringEncoding];
}

- (NSString *)authCodeDecoded:(NSString *)key encoding:(NSStringEncoding)encoding
{
    return [self authCode:key operation:NSStringAuthCodeDecoded encoding:encoding];
}

- (NSString *)authCodeDecoded:(NSString *)key
{
    return [self authCodeDecoded:key encoding:NSUTF8StringEncoding];
}

@end


    NSString *key = @"123";
    NSString *string = @"test";
    NSString *a = [string authCodeEncoded:key];
    NSLog(@"%@",a);
    NSLog(@"%@",[a authCodeDecoded:key]);


完整代码下载地址:http://download.csdn.net/detail/jxncwzb/8474547


Java中也有类似的加密解密算法可以实现类似PHPauthcode功能。常见的加密解密算法有AES、DES、RSA等。 以AES算法为例,可以使用Java内置的javax.crypto库中的AES算法实现加密解密。 加密示例代码: ``` import javax.crypto.Cipher; import javax.crypto.spec.SecretKeySpec; import org.apache.commons.codec.binary.Base64; public class AESUtil { //默认密钥 private static final String DEFAULT_SECRET_KEY = "1234567890abcdef"; /** * AES加密 * @param content 待加密内容 * @param secretKey 密钥 * @return 加密后的内容 */ public static String encrypt(String content, String secretKey) { try { Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding"); SecretKeySpec keySpec = new SecretKeySpec(secretKey.getBytes("UTF-8"), "AES"); cipher.init(Cipher.ENCRYPT_MODE, keySpec); byte[] encrypted = cipher.doFinal(content.getBytes("UTF-8")); return Base64.encodeBase64String(encrypted); } catch (Exception e) { e.printStackTrace(); } return null; } /** * AES加密,默认使用默认密钥 * @param content 待加密内容 * @return 加密后的内容 */ public static String encrypt(String content) { return encrypt(content, DEFAULT_SECRET_KEY); } } ``` 解密示例代码: ``` import javax.crypto.Cipher; import javax.crypto.spec.SecretKeySpec; import org.apache.commons.codec.binary.Base64; public class AESUtil { //默认密钥 private static final String DEFAULT_SECRET_KEY = "1234567890abcdef"; /** * AES解密 * @param content 待解密内容 * @param secretKey 密钥 * @return 解密后的内容 */ public static String decrypt(String content, String secretKey) { try { Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding"); SecretKeySpec keySpec = new SecretKeySpec(secretKey.getBytes("UTF-8"), "AES"); cipher.init(Cipher.DECRYPT_MODE, keySpec); byte[] decrypted = cipher.doFinal(Base64.decodeBase64(content)); return new String(decrypted, "UTF-8"); } catch (Exception e) { e.printStackTrace(); } return null; } /** * AES解密,默认使用默认密钥 * @param content 待解密内容 * @return 解密后的内容 */ public static String decrypt(String content) { return decrypt(content, DEFAULT_SECRET_KEY); } } ``` 使用示例: ``` String content = "hello world"; String secretKey = "1234567890abcdef"; //加密 String encryptedContent = AESUtil.encrypt(content, secretKey); System.out.println("加密后的内容:" + encryptedContent); //解密 String decryptedContent = AESUtil.decrypt(encryptedContent, secretKey); System.out.println("解密后的内容:" + decryptedContent); ``` 输出: ``` 加密后的内容:wK0MwIxt8GQ4JUQXHcJ5Og== 解密后的内容:hello world ``` 需要注意的是,加密和解密需要使用相同的密钥才能得到正确的结果。因此在实际使用中,密钥需要进行安全保管,避免泄露。
评论 15
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值