java、android、io、php通用的3des加密方法

本文介绍了一种在PHP、Java、iOS等多个平台上一致的3DES加密方法,并提供了详细的代码示例,帮助开发者轻松实现跨平台的数据加密。

个人在使用的时候,测试java版本没有问题,ios的需要注意base64转换编码的问题,会出现/+等字符转义失败的情况,详情参考下面的参考文件 ,下面的方法在项目中使用过 php未使用过。

php

[php]  view plain  copy
  1. <?php  
  2. class DES3 {  
  3.     var $key = "my.oschina.net/penngo?#@";  
  4.     var $iv = "01234567";  
  5.    
  6.     function encrypt($input){  
  7.         $size = mcrypt_get_block_size(MCRYPT_3DES,MCRYPT_MODE_CBC);  
  8.         $input = $this->pkcs5_pad($input$size);  
  9.         $key = str_pad($this->key,24,'0');  
  10.         $td = mcrypt_module_open(MCRYPT_3DES, '', MCRYPT_MODE_CBC, '');  
  11.         if$this->iv == '' )  
  12.         {  
  13.             $iv = @mcrypt_create_iv (mcrypt_enc_get_iv_size($td), MCRYPT_RAND);  
  14.         }  
  15.         else  
  16.         {  
  17.             $iv = $this->iv;  
  18.         }  
  19.         @mcrypt_generic_init($td$key$iv);  
  20.         $data = mcrypt_generic($td$input);  
  21.         mcrypt_generic_deinit($td);  
  22.         mcrypt_module_close($td);  
  23.         $data = base64_encode($data);  
  24.         return $data;  
  25.     }  
  26.     function decrypt($encrypted){  
  27.         $encrypted = base64_decode($encrypted);  
  28.         $key = str_pad($this->key,24,'0');  
  29.         $td = mcrypt_module_open(MCRYPT_3DES,'',MCRYPT_MODE_CBC,'');  
  30.         if$this->iv == '' )  
  31.         {  
  32.             $iv = @mcrypt_create_iv (mcrypt_enc_get_iv_size($td), MCRYPT_RAND);  
  33.         }  
  34.         else  
  35.         {  
  36.             $iv = $this->iv;  
  37.         }  
  38.         $ks = mcrypt_enc_get_key_size($td);  
  39.         @mcrypt_generic_init($td$key$iv);  
  40.         $decrypted = mdecrypt_generic($td$encrypted);  
  41.         mcrypt_generic_deinit($td);  
  42.         mcrypt_module_close($td);  
  43.         $y=$this->pkcs5_unpad($decrypted);  
  44.         return $y;  
  45.     }  
  46.     function pkcs5_pad ($text$blocksize) {  
  47.         $pad = $blocksize - (strlen($text) % $blocksize);  
  48.         return $text . str_repeat(chr($pad), $pad);  
  49.     }  
  50.     function pkcs5_unpad($text){  
  51.         $pad = ord($text{strlen($text)-1});  
  52.         if ($pad > strlen($text)) {  
  53.             return false;  
  54.         }  
  55.         if (strspn($textchr($pad), strlen($text) - $pad) != $pad){  
  56.             return false;  
  57.         }  
  58.         return substr($text, 0, -1 * $pad);  
  59.     }  
  60.     function PaddingPKCS7($data) {  
  61.         $block_size = mcrypt_get_block_size(MCRYPT_3DES, MCRYPT_MODE_CBC);  
  62.         $padding_char = $block_size - (strlen($data) % $block_size);  
  63.         $data .= str_repeat(chr($padding_char),$padding_char);  
  64.         return $data;  
  65.     }  
  66. }  
  67.    
  68. $des = new DES3();  
  69. echo $ret = $des->encrypt("来自http://my.oschina.net/penngo的博客") . "\n";  
  70. echo $des->decrypt($ret) . "\n";  


java(android)

[java]  view plain  copy
  1. import java.io.ByteArrayOutputStream;  
  2. import java.io.IOException;  
  3. import java.io.OutputStream;  
  4. import java.io.UnsupportedEncodingException;  
  5. import java.security.Key;    
  6.   
  7. import javax.crypto.Cipher;    
  8. import javax.crypto.SecretKeyFactory;    
  9. import javax.crypto.spec.DESedeKeySpec;    
  10. import javax.crypto.spec.IvParameterSpec;    
  11.           
  12. /**  
  13.   * 3DES加密工具类  
  14.   */   
  15. public class DES3 {    
  16.      // 密钥    
  17.      private final static String secretKey = "my.oschina.net/penngo?#@" ;     
  18.      // 向量    
  19.      private final static String iv = "01234567" ;    
  20.      // 加解密统一使用的编码方式    
  21.      private final static String encoding = "utf-8" ;    
  22.           
  23.      /**  
  24.       * 3DES加密  
  25.       *   
  26.       * @param plainText 普通文本  
  27.       * @return  
  28.       * @throws Exception   
  29.       */   
  30.      public static String encode(String plainText) throws Exception {    
  31.          Key deskey = null ;    
  32.          DESedeKeySpec spec = new DESedeKeySpec(secretKey.getBytes());    
  33.          SecretKeyFactory keyfactory = SecretKeyFactory.getInstance( "desede" );    
  34.          deskey = keyfactory.generateSecret(spec);    
  35.           
  36.          Cipher cipher = Cipher.getInstance( "desede/CBC/PKCS5Padding" );    
  37.          IvParameterSpec ips = new IvParameterSpec(iv.getBytes());    
  38.          cipher.init(Cipher.ENCRYPT_MODE, deskey, ips);    
  39.          byte [] encryptData = cipher.doFinal(plainText.getBytes(encoding));    
  40.          return Base64.encode(encryptData);    
  41.      }    
  42.           
  43.      /**  
  44.       * 3DES解密  
  45.       *   
  46.       * @param encryptText 加密文本  
  47.       * @return  
  48.       * @throws Exception  
  49.       */   
  50.      public static String decode(String encryptText) throws Exception {    
  51.          Key deskey = null ;    
  52.          DESedeKeySpec spec = new DESedeKeySpec(secretKey.getBytes());     
  53.          SecretKeyFactory keyfactory = SecretKeyFactory.getInstance( "desede" );    
  54.          deskey = keyfactory.generateSecret(spec);    
  55.          Cipher cipher = Cipher.getInstance( "desede/CBC/PKCS5Padding" );    
  56.          IvParameterSpec ips = new IvParameterSpec(iv.getBytes());    
  57.          cipher.init(Cipher.DECRYPT_MODE, deskey, ips);    
  58.           
  59.          byte [] decryptData = cipher.doFinal(Base64.decode(encryptText));    
  60.           
  61.          return new String(decryptData, encoding);    
  62.      }    
  63.        
  64.     public static String padding(String str) {  
  65.         byte[] oldByteArray;  
  66.         try {  
  67.             oldByteArray = str.getBytes("UTF8");  
  68.             int numberToPad = 8 - oldByteArray.length % 8;  
  69.             byte[] newByteArray = new byte[oldByteArray.length + numberToPad];  
  70.             System.arraycopy(oldByteArray, 0, newByteArray, 0,  
  71.                     oldByteArray.length);  
  72.             for (int i = oldByteArray.length; i < newByteArray.length; ++i) {  
  73.                 newByteArray[i] = 0;  
  74.             }  
  75.             return new String(newByteArray, "UTF8");  
  76.         } catch (UnsupportedEncodingException e) {  
  77.             System.out.println("Crypter.padding UnsupportedEncodingException");  
  78.         }  
  79.         return null;  
  80.     }  
  81.       
  82.     /**  
  83.       * Base64编码工具类  
  84.       *  
  85.       */   
  86.     public static class Base64 {    
  87.          private static final char [] legalChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_" .toCharArray();    
  88.               
  89.          public static String encode( byte [] data) {    
  90.              int start = 0 ;    
  91.              int len = data.length;    
  92.              StringBuffer buf = new StringBuffer(data.length * 3 / 2 );    
  93.               
  94.              int end = len - 3 ;    
  95.              int i = start;    
  96.              int n = 0 ;    
  97.               
  98.              while (i <= end) {    
  99.                  int d = (((( int ) data[i]) & 0x0ff ) << 16 ) | (((( int ) data[i + 1 ]) & 0x0ff ) << 8 ) | ((( int ) data[i + 2 ]) & 0x0ff );    
  100.               
  101.                  buf.append(legalChars[(d >> 18 ) & 63 ]);    
  102.                  buf.append(legalChars[(d >> 12 ) & 63 ]);    
  103.                  buf.append(legalChars[(d >> 6 ) & 63 ]);    
  104.                  buf.append(legalChars[d & 63 ]);    
  105.               
  106.                  i += 3 ;    
  107.               
  108.                  if (n++ >= 14 ) {    
  109.                      n = 0 ;    
  110.                      buf.append( " " );    
  111.                  }    
  112.              }    
  113.               
  114.              if (i == start + len - 2 ) {    
  115.                  int d = (((( int ) data[i]) & 0x0ff ) << 16 ) | (((( int ) data[i + 1 ]) & 255 ) << 8 );    
  116.               
  117.                  buf.append(legalChars[(d >> 18 ) & 63 ]);    
  118.                  buf.append(legalChars[(d >> 12 ) & 63 ]);    
  119.                  buf.append(legalChars[(d >> 6 ) & 63 ]);    
  120.                  buf.append( "=" );    
  121.              } else if (i == start + len - 1 ) {    
  122.                  int d = ((( int ) data[i]) & 0x0ff ) << 16 ;    
  123.               
  124.                  buf.append(legalChars[(d >> 18 ) & 63 ]);    
  125.                  buf.append(legalChars[(d >> 12 ) & 63 ]);    
  126.                  buf.append( "==" );    
  127.              }    
  128.               
  129.              return buf.toString();    
  130.          }    
  131.               
  132.          private static int decode( char c) {    
  133.              if (c >= 'A' && c <= 'Z' )    
  134.                  return (( int ) c) - 65 ;    
  135.              else if (c >= 'a' && c <= 'z' )    
  136.                  return (( int ) c) - 97 + 26 ;    
  137.              else if (c >= '0' && c <= '9' )    
  138.                  return (( int ) c) - 48 + 26 + 26 ;    
  139.              else   
  140.                  switch (c) {    
  141.                  case '-' :    
  142.                      return 62 ;    
  143.                  case '_' :    
  144.                      return 63 ;    
  145.                  case '=' :    
  146.                      return 0 ;    
  147.                  default :    
  148.                      throw new RuntimeException( "unexpected code: " + c);    
  149.                  }    
  150.          }    
  151.               
  152.          /**  
  153.           * Decodes the given Base64 encoded String to a new byte array. The byte array holding the decoded data is returned.  
  154.           */   
  155.               
  156.          public static byte [] decode(String s) {    
  157.               
  158.              ByteArrayOutputStream bos = new ByteArrayOutputStream();    
  159.              try {    
  160.                  decode(s, bos);    
  161.              } catch (IOException e) {    
  162.                  throw new RuntimeException();    
  163.              }    
  164.              byte [] decodedBytes = bos.toByteArray();    
  165.              try {    
  166.                  bos.close();    
  167.                  bos = null ;    
  168.              } catch (IOException ex) {    
  169.                  System.err.println( "Error while decoding BASE64: " + ex.toString());    
  170.              }    
  171.              return decodedBytes;    
  172.          }    
  173.               
  174.          private static void decode(String s, OutputStream os) throws IOException {    
  175.              int i = 0 ;    
  176.               
  177.              int len = s.length();    
  178.               
  179.              while ( true ) {    
  180.                  while (i < len && s.charAt(i) <= ' ' )    
  181.                      i++;    
  182.               
  183.                  if (i == len)    
  184.                      break ;    
  185.               
  186.                  int tri = (decode(s.charAt(i)) << 18 ) + (decode(s.charAt(i + 1 )) << 12 ) + (decode(s.charAt(i + 2 )) << 6 ) + (decode(s.charAt(i + 3 )));    
  187.               
  188.                  os.write((tri >> 16 ) & 255 );    
  189.                  if (s.charAt(i + 2 ) == '=' )    
  190.                      break ;    
  191.                  os.write((tri >> 8 ) & 255 );    
  192.                  if (s.charAt(i + 3 ) == '=' )    
  193.                      break ;    
  194.                  os.write(tri & 255 );    
  195.               
  196.                  i += 4 ;    
  197.              }    
  198.          }    
  199.     }   
  200.        
  201.      public static void main(String[] args) throws Exception{  
  202.          String plainText = "来自http://my.oschina.net/penngo的博客";  
  203.          String encryptText = DES3.encode(plainText);  
  204.          System.out.println(encryptText);  
  205.          System.out.println(DES3.decode(encryptText));  
  206.   
  207.            
  208.      }  
  209. }  


Ojbective-C(ios)

[objc]  view plain  copy
  1. //    
  2. //  DES3Util.h    
  3. //    
  4. #import <Foundation/Foundation.h>    
  5. @interface DES3Util : NSObject {    
  6. }    
  7. // 加密方法    
  8. + (NSString*)encrypt:(NSString*)plainText;    
  9. // 解密方法    
  10. + (NSString*)decrypt:(NSString*)encryptText;    
  11. @end   
  12.   
  13.   
  14. //    
  15. //  DES3Util.m    
  16. //    
  17.           
  18. #import "DES3Util.h"    
  19. #import <CommonCrypto/CommonCryptor.h>    
  20. #import "GTMBase64.h"    
  21. #define gkey            @"my.oschina.net/penngo?#@"    
  22. #define gIv             @"01234567"    
  23.           
  24. @implementation DES3Util    
  25. // 加密方法    
  26. + (NSString*)encrypt:(NSString*)plainText {    
  27.      NSData* data = [plainText dataUsingEncoding:NSUTF8StringEncoding];    
  28.      size_t plainTextBufferSize = [data length];    
  29.      const voidvoid *vplainText = (const voidvoid *)[data bytes];    
  30.               
  31.      CCCryptorStatus ccStatus;    
  32.      uint8_t *bufferPtr = NULL;    
  33.      size_t bufferPtrSize = 0;    
  34.      size_t movedBytes = 0;    
  35.               
  36.      bufferPtrSize = (plainTextBufferSize + kCCBlockSize3DES) & ~(kCCBlockSize3DES - 1);    
  37.      bufferPtr = malloc( bufferPtrSize * sizeof(uint8_t));    
  38.      memset((voidvoid *)bufferPtr, 0x0, bufferPtrSize);    
  39.               
  40.      const voidvoid *vkey = (const voidvoid *) [gkey UTF8String];    
  41.      const voidvoid *vinitVec = (const voidvoid *) [gIv UTF8String];    
  42.               
  43.      ccStatus = CCCrypt(kCCEncrypt,    
  44.                         kCCAlgorithm3DES,    
  45.                         kCCOptionPKCS7Padding,    
  46.                         vkey,    
  47.                         kCCKeySize3DES,    
  48.                         vinitVec,    
  49.                         vplainText,    
  50.                         plainTextBufferSize,    
  51.                         (voidvoid *)bufferPtr,    
  52.                         bufferPtrSize,    
  53.                         &movedBytes);    
  54.               
  55.      NSData *myData = [NSData dataWithBytes:(const voidvoid *)bufferPtr length:(NSUInteger)movedBytes];    
  56.      NSString *result = [GTMBase64 stringByEncodingData:myData];    
  57.      return result;    
  58. }    
  59.           
  60. // 解密方法    
  61. + (NSString*)decrypt:(NSString*)encryptText {    
  62.      NSData *encryptData = [GTMBase64 decodeData:[encryptText dataUsingEncoding:NSUTF8StringEncoding]];    
  63.      size_t plainTextBufferSize = [encryptData length];    
  64.      const voidvoid *vplainText = [encryptData bytes];    
  65.               
  66.      CCCryptorStatus ccStatus;    
  67.      uint8_t *bufferPtr = NULL;    
  68.      size_t bufferPtrSize = 0;    
  69.      size_t movedBytes = 0;    
  70.      bufferPtrSize = (plainTextBufferSize + kCCBlockSize3DES) & ~(kCCBlockSize3DES - 1);    
  71.      bufferPtr = malloc( bufferPtrSize * sizeof(uint8_t));    
  72.      memset((voidvoid *)bufferPtr, 0x0, bufferPtrSize);       
  73.      const voidvoid *vkey = (const voidvoid *) [gkey UTF8String];    
  74.      const voidvoid *vinitVec = (const voidvoid *) [gIv UTF8String];    
  75.               
  76.      ccStatus = CCCrypt(kCCDecrypt,    
  77.                         kCCAlgorithm3DES,    
  78.                         kCCOptionPKCS7Padding,    
  79.                         vkey,    
  80.                         kCCKeySize3DES,    
  81.                         vinitVec,    
  82.                         vplainText,    
  83.                         plainTextBufferSize,    
  84.                         (voidvoid *)bufferPtr,    
  85.                         bufferPtrSize,    
  86.                         &movedBytes);    
  87.               
  88.      NSString *result = [[[NSString alloc] initWithData:[NSData dataWithBytes:(const voidvoid *)bufferPtr     
  89.                                  length:(NSUInteger)movedBytes] encoding:NSUTF8StringEncoding] autorelease];    
  90.      return result;    
  91. }    
  92.           
  93. @end  
  94.   
  95. //  
  96. //  GTMBase64.h  
  97. //  
  98. //  Copyright 2006-2008 Google Inc.  
  99. //  
  100. //  Licensed under the Apache License, Version 2.0 (the "License"); you may not  
  101. //  use this file except in compliance with the License.  You may obtain a copy  
  102. //  of the License at  
  103. //  
  104. //  http://www.apache.org/licenses/LICENSE-2.0  
  105. //  
  106. //  Unless required by applicable law or agreed to in writing, software  
  107. //  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT  
  108. //  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the  
  109. //  License for the specific language governing permissions and limitations under  
  110. //  the License.  
  111.   
  112. // David Lee make changes:  
  113. // Remove dependency on GTMDefines.h  
  114. // add some string to string function  
  115.   
  116. #import <Foundation/Foundation.h>  
  117.   
  118. // GTMBase64  
  119. //  
  120. /// Helper for handling Base64 and WebSafeBase64 encodings  
  121. //  
  122. /// The webSafe methods use different character set and also the results aren't  
  123. /// always padded to a multiple of 4 characters.  This is done so the resulting  
  124. /// data can be used in urls and url query arguments without needing any  
  125. /// encoding.  You must use the webSafe* methods together, the data does not  
  126. /// interop with the RFC methods.  
  127. //  
  128. @interface GTMBase64 : NSObject  
  129.   
  130. //  
  131. // Standard Base64 (RFC) handling  
  132. //  
  133.   
  134. // encodeData:  
  135. //  
  136. /// Base64 encodes contents of the NSData object.  
  137. //  
  138. /// Returns:  
  139. ///   A new autoreleased NSData with the encoded payload.  nil for any error.  
  140. //  
  141. +(NSData *)encodeData:(NSData *)data;  
  142.   
  143. // decodeData:  
  144. //  
  145. /// Base64 decodes contents of the NSData object.  
  146. //  
  147. /// Returns:  
  148. ///   A new autoreleased NSData with the decoded payload.  nil for any error.  
  149. //  
  150. +(NSData *)decodeData:(NSData *)data;  
  151.   
  152. // encodeBytes:length:  
  153. //  
  154. /// Base64 encodes the data pointed at by |bytes|.  
  155. //  
  156. /// Returns:  
  157. ///   A new autoreleased NSData with the encoded payload.  nil for any error.  
  158. //  
  159. +(NSData *)encodeBytes:(const voidvoid *)bytes length:(NSUInteger)length;  
  160.   
  161. // decodeBytes:length:  
  162. //  
  163. /// Base64 decodes the data pointed at by |bytes|.  
  164. //  
  165. /// Returns:  
  166. ///   A new autoreleased NSData with the encoded payload.  nil for any error.  
  167. //  
  168. +(NSData *)decodeBytes:(const voidvoid *)bytes length:(NSUInteger)length;  
  169.   
  170. // stringByEncodingData:  
  171. //  
  172. /// Base64 encodes contents of the NSData object.  
  173. //  
  174. /// Returns:  
  175. ///   A new autoreleased NSString with the encoded payload.  nil for any error.  
  176. //  
  177. +(NSString *)stringByEncodingData:(NSData *)data;  
  178.   
  179. // stringByEncodingBytes:length:  
  180. //  
  181. /// Base64 encodes the data pointed at by |bytes|.  
  182. //  
  183. /// Returns:  
  184. ///   A new autoreleased NSString with the encoded payload.  nil for any error.  
  185. //  
  186. +(NSString *)stringByEncodingBytes:(const voidvoid *)bytes length:(NSUInteger)length;  
  187.   
  188. // decodeString:  
  189. //  
  190. /// Base64 decodes contents of the NSString.  
  191. //  
  192. /// Returns:  
  193. ///   A new autoreleased NSData with the decoded payload.  nil for any error.  
  194. //  
  195. +(NSData *)decodeString:(NSString *)string;  
  196.   
  197. //  
  198. // Modified Base64 encoding so the results can go onto urls.  
  199. //  
  200. // The changes are in the characters generated and also allows the result to  
  201. // not be padded to a multiple of 4.  
  202. // Must use the matching call to encode/decode, won't interop with the  
  203. // RFC versions.  
  204. //  
  205.   
  206. // webSafeEncodeData:padded:  
  207. //  
  208. /// WebSafe Base64 encodes contents of the NSData object.  If |padded| is YES  
  209. /// then padding characters are added so the result length is a multiple of 4.  
  210. //  
  211. /// Returns:  
  212. ///   A new autoreleased NSData with the encoded payload.  nil for any error.  
  213. //  
  214. +(NSData *)webSafeEncodeData:(NSData *)data  
  215.                       padded:(BOOL)padded;  
  216.   
  217. // webSafeDecodeData:  
  218. //  
  219. /// WebSafe Base64 decodes contents of the NSData object.  
  220. //  
  221. /// Returns:  
  222. ///   A new autoreleased NSData with the decoded payload.  nil for any error.  
  223. //  
  224. +(NSData *)webSafeDecodeData:(NSData *)data;  
  225.   
  226. // webSafeEncodeBytes:length:padded:  
  227. //  
  228. /// WebSafe Base64 encodes the data pointed at by |bytes|.  If |padded| is YES  
  229. /// then padding characters are added so the result length is a multiple of 4.  
  230. //  
  231. /// Returns:  
  232. ///   A new autoreleased NSData with the encoded payload.  nil for any error.  
  233. //  
  234. +(NSData *)webSafeEncodeBytes:(const voidvoid *)bytes  
  235.                        length:(NSUInteger)length  
  236.                        padded:(BOOL)padded;  
  237.   
  238. // webSafeDecodeBytes:length:  
  239. //  
  240. /// WebSafe Base64 decodes the data pointed at by |bytes|.  
  241. //  
  242. /// Returns:  
  243. ///   A new autoreleased NSData with the encoded payload.  nil for any error.  
  244. //  
  245. +(NSData *)webSafeDecodeBytes:(const voidvoid *)bytes length:(NSUInteger)length;  
  246.   
  247. // stringByWebSafeEncodingData:padded:  
  248. //  
  249. /// WebSafe Base64 encodes contents of the NSData object.  If |padded| is YES  
  250. /// then padding characters are added so the result length is a multiple of 4.  
  251. //  
  252. /// Returns:  
  253. ///   A new autoreleased NSString with the encoded payload.  nil for any error.  
  254. //  
  255. +(NSString *)stringByWebSafeEncodingData:(NSData *)data  
  256.                                   padded:(BOOL)padded;  
  257.   
  258. // stringByWebSafeEncodingBytes:length:padded:  
  259. //  
  260. /// WebSafe Base64 encodes the data pointed at by |bytes|.  If |padded| is YES  
  261. /// then padding characters are added so the result length is a multiple of 4.  
  262. //  
  263. /// Returns:  
  264. ///   A new autoreleased NSString with the encoded payload.  nil for any error.  
  265. //  
  266. +(NSString *)stringByWebSafeEncodingBytes:(const voidvoid *)bytes  
  267.                                    length:(NSUInteger)length  
  268.                                    padded:(BOOL)padded;  
  269.   
  270. // webSafeDecodeString:  
  271. //  
  272. /// WebSafe Base64 decodes contents of the NSString.  
  273. //  
  274. /// Returns:  
  275. ///   A new autoreleased NSData with the decoded payload.  nil for any error.  
  276. //  
  277. +(NSData *)webSafeDecodeString:(NSString *)string;  
  278.   
  279. // David Lee new added function  
  280. /// Returns:  
  281. // A new autoreleased NSString with Base64 encoded NSString  
  282. +(NSString *)stringByBase64String:(NSString *)base64String;  
  283.   
  284. // David Lee new added function  
  285. /// Returns:  
  286. // A new autoreleased Base64 encoded NSString with  NSString  
  287. +(NSString *)base64StringBystring:(NSString *)string;  
  288. @end  
  289.   
  290.   
  291. //  
  292. //  GTMBase64.m  
  293. //  
  294. //  Copyright 2006-2008 Google Inc.  
  295. //  
  296. //  Licensed under the Apache License, Version 2.0 (the "License"); you may not  
  297. //  use this file except in compliance with the License.  You may obtain a copy  
  298. //  of the License at  
  299. //  
  300. //  http://www.apache.org/licenses/LICENSE-2.0  
  301. //  
  302. //  Unless required by applicable law or agreed to in writing, software  
  303. //  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT  
  304. //  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the  
  305. //  License for the specific language governing permissions and limitations under  
  306. //  the License.  
  307. // David Lee make changes:  
  308. // Remove dependency on GTMDefines.h  
  309. // add some string to string function  
  310.   
  311. #import "GTMBase64.h"  
  312.   
  313. static const charchar *kBase64EncodeChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";  
  314. static const charchar *kWebSafeBase64EncodeChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";  
  315. static const char kBase64PaddingChar = '=';  
  316. static const char kBase64InvalidChar = 99;  
  317.   
  318. static const char kBase64DecodeChars[] = {  
  319.     // This array was generated by the following code:  
  320.     // #include <sys/time.h>  
  321.     // #include <stdlib.h>  
  322.     // #include <string.h>  
  323.     // main()  
  324.     // {  
  325.     //   static const char Base64[] =  
  326.     //     "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";  
  327.     //   char *pos;  
  328.     //   int idx, i, j;  
  329.     //   printf("    ");  
  330.     //   for (i = 0; i < 255; i += 8) {  
  331.     //     for (j = i; j < i + 8; j++) {  
  332.     //       pos = strchr(Base64, j);  
  333.     //       if ((pos == NULL) || (j == 0))  
  334.     //         idx = 99;  
  335.     //       else  
  336.     //         idx = pos - Base64;  
  337.     //       if (idx == 99)  
  338.     //         printf(" %2d,     ", idx);  
  339.     //       else  
  340.     //         printf(" %2d/*%c*/,", idx, j);  
  341.     //     }  
  342.     //     printf("\n    ");  
  343.     //   }  
  344.     // }  
  345.     99,      99,      99,      99,      99,      99,      99,      99,  
  346.     99,      99,      99,      99,      99,      99,      99,      99,  
  347.     99,      99,      99,      99,      99,      99,      99,      99,  
  348.     99,      99,      99,      99,      99,      99,      99,      99,  
  349.     99,      99,      99,      99,      99,      99,      99,      99,  
  350.     99,      99,      99,      62/*+*/99,      99,      99,      63/*/ */,  
  351.     52/*0*/53/*1*/54/*2*/55/*3*/56/*4*/57/*5*/58/*6*/59/*7*/,  
  352.     60/*8*/61/*9*/99,      99,      99,      99,      99,      99,  
  353.     99,       0/*A*/,  1/*B*/,  2/*C*/,  3/*D*/,  4/*E*/,  5/*F*/,  6/*G*/,  
  354.     7/*H*/,  8/*I*/,  9/*J*/10/*K*/11/*L*/12/*M*/13/*N*/14/*O*/,  
  355.     15/*P*/16/*Q*/17/*R*/18/*S*/19/*T*/20/*U*/21/*V*/22/*W*/,  
  356.     23/*X*/24/*Y*/25/*Z*/99,      99,      99,      99,      99,  
  357.     99,      26/*a*/27/*b*/28/*c*/29/*d*/30/*e*/31/*f*/32/*g*/,  
  358.     33/*h*/34/*i*/35/*j*/36/*k*/37/*l*/38/*m*/39/*n*/40/*o*/,  
  359.     41/*p*/42/*q*/43/*r*/44/*s*/45/*t*/46/*u*/47/*v*/48/*w*/,  
  360.     49/*x*/50/*y*/51/*z*/99,      99,      99,      99,      99,  
  361.     99,      99,      99,      99,      99,      99,      99,      99,  
  362.     99,      99,      99,      99,      99,      99,      99,      99,  
  363.     99,      99,      99,      99,      99,      99,      99,      99,  
  364.     99,      99,      99,      99,      99,      99,      99,      99,  
  365.     99,      99,      99,      99,      99,      99,      99,      99,  
  366.     99,      99,      99,      99,      99,      99,      99,      99,  
  367.     99,      99,      99,      99,      99,      99,      99,      99,  
  368.     99,      99,      99,      99,      99,      99,      99,      99,  
  369.     99,      99,      99,      99,      99,      99,      99,      99,  
  370.     99,      99,      99,      99,      99,      99,      99,      99,  
  371.     99,      99,      99,      99,      99,      99,      99,      99,  
  372.     99,      99,      99,      99,      99,      99,      99,      99,  
  373.     99,      99,      99,      99,      99,      99,      99,      99,  
  374.     99,      99,      99,      99,      99,      99,      99,      99,  
  375.     99,      99,      99,      99,      99,      99,      99,      99,  
  376.     99,      99,      99,      99,      99,      99,      99,      99  
  377. };  
  378.   
  379. static const char kWebSafeBase64DecodeChars[] = {  
  380.     // This array was generated by the following code:  
  381.     // #include <sys/time.h>  
  382.     // #include <stdlib.h>  
  383.     // #include <string.h>  
  384.     // main()  
  385.     // {  
  386.     //   static const char Base64[] =  
  387.     //     "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";  
  388.     //   char *pos;  
  389.     //   int idx, i, j;  
  390.     //   printf("    ");  
  391.     //   for (i = 0; i < 255; i += 8) {  
  392.     //     for (j = i; j < i + 8; j++) {  
  393.     //       pos = strchr(Base64, j);  
  394.     //       if ((pos == NULL) || (j == 0))  
  395.     //         idx = 99;  
  396.     //       else  
  397.     //         idx = pos - Base64;  
  398.     //       if (idx == 99)  
  399.     //         printf(" %2d,     ", idx);  
  400.     //       else  
  401.     //         printf(" %2d/*%c*/,", idx, j);  
  402.     //     }  
  403.     //     printf("\n    ");  
  404.     //   }  
  405.     // }  
  406.     99,      99,      99,      99,      99,      99,      99,      99,  
  407.     99,      99,      99,      99,      99,      99,      99,      99,  
  408.     99,      99,      99,      99,      99,      99,      99,      99,  
  409.     99,      99,      99,      99,      99,      99,      99,      99,  
  410.     99,      99,      99,      99,      99,      99,      99,      99,  
  411.     99,      99,      99,      99,      99,      62/*-*/99,      99,  
  412.     52/*0*/53/*1*/54/*2*/55/*3*/56/*4*/57/*5*/58/*6*/59/*7*/,  
  413.     60/*8*/61/*9*/99,      99,      99,      99,      99,      99,  
  414.     99,       0/*A*/,  1/*B*/,  2/*C*/,  3/*D*/,  4/*E*/,  5/*F*/,  6/*G*/,  
  415.     7/*H*/,  8/*I*/,  9/*J*/10/*K*/11/*L*/12/*M*/13/*N*/14/*O*/,  
  416.     15/*P*/16/*Q*/17/*R*/18/*S*/19/*T*/20/*U*/21/*V*/22/*W*/,  
  417.     23/*X*/24/*Y*/25/*Z*/99,      99,      99,      99,      63/*_*/,  
  418.     99,      26/*a*/27/*b*/28/*c*/29/*d*/30/*e*/31/*f*/32/*g*/,  
  419.     33/*h*/34/*i*/35/*j*/36/*k*/37/*l*/38/*m*/39/*n*/40/*o*/,  
  420.     41/*p*/42/*q*/43/*r*/44/*s*/45/*t*/46/*u*/47/*v*/48/*w*/,  
  421.     49/*x*/50/*y*/51/*z*/99,      99,      99,      99,      99,  
  422.     99,      99,      99,      99,      99,      99,      99,      99,  
  423.     99,      99,      99,      99,      99,      99,      99,      99,  
  424.     99,      99,      99,      99,      99,      99,      99,      99,  
  425.     99,      99,      99,      99,      99,      99,      99,      99,  
  426.     99,      99,      99,      99,      99,      99,      99,      99,  
  427.     99,      99,      99,      99,      99,      99,      99,      99,  
  428.     99,      99,      99,      99,      99,      99,      99,      99,  
  429.     99,      99,      99,      99,      99,      99,      99,      99,  
  430.     99,      99,      99,      99,      99,      99,      99,      99,  
  431.     99,      99,      99,      99,      99,      99,      99,      99,  
  432.     99,      99,      99,      99,      99,      99,      99,      99,  
  433.     99,      99,      99,      99,      99,      99,      99,      99,  
  434.     99,      99,      99,      99,      99,      99,      99,      99,  
  435.     99,      99,      99,      99,      99,      99,      99,      99,  
  436.     99,      99,      99,      99,      99,      99,      99,      99,  
  437.     99,      99,      99,      99,      99,      99,      99,      99  
  438. };  
  439.   
  440.   
  441. // Tests a character to see if it's a whitespace character.  
  442. //  
  443. // Returns:  
  444. //   YES if the character is a whitespace character.  
  445. //   NO if the character is not a whitespace character.  
  446. //  
  447. BOOL IsSpace(unsigned char c) {  
  448.     // we use our own mapping here because we don't want anything w/ locale  
  449.     // support.  
  450.     static BOOL kSpaces[256] = {  
  451.         0000000001,  // 0-9  
  452.         1111000000,  // 10-19  
  453.         0000000000,  // 20-29  
  454.         0010000000,  // 30-39  
  455.         0000000000,  // 40-49  
  456.         0000000000,  // 50-59  
  457.         0000000000,  // 60-69  
  458.         0000000000,  // 70-79  
  459.         0000000000,  // 80-89  
  460.         0000000000,  // 90-99  
  461.         0000000000,  // 100-109  
  462.         0000000000,  // 110-119  
  463.         0000000000,  // 120-129  
  464.         0000000000,  // 130-139  
  465.         0000000000,  // 140-149  
  466.         0000000000,  // 150-159  
  467.         1000000000,  // 160-169  
  468.         0000000000,  // 170-179  
  469.         0000000000,  // 180-189  
  470.         0000000000,  // 190-199  
  471.         0000000000,  // 200-209  
  472.         0000000000,  // 210-219  
  473.         0000000000,  // 220-229  
  474.         0000000000,  // 230-239  
  475.         0000000000,  // 240-249  
  476.         000001,              // 250-255  
  477.     };  
  478.     return kSpaces[c];  
  479. }  
  480.   
  481. // Calculate how long the data will be once it's base64 encoded.  
  482. //  
  483. // Returns:  
  484. //   The guessed encoded length for a source length  
  485. //  
  486. NSUInteger CalcEncodedLength(NSUInteger srcLen, BOOL padded) {  
  487.     NSUInteger intermediate_result = 88 * srcLen + 5;  
  488.     NSUInteger len = intermediate_result / 6;  
  489.     if (padded) {  
  490.         len = ((len + 3) / 4) * 4;  
  491.     }  
  492.     return len;  
  493. }  
  494.   
  495. // Tries to calculate how long the data will be once it's base64 decoded.  
  496. // Unlike the above, this is always an upperbound, since the source data  
  497. // could have spaces and might end with the padding characters on them.  
  498. //  
  499. // Returns:  
  500. //   The guessed decoded length for a source length  
  501. //  
  502. NSUInteger GuessDecodedLength(NSUInteger srcLen) {  
  503.     return (srcLen + 3) / 44 * 3;  
  504. }  
  505.   
  506.   
  507. @interface GTMBase64 (PrivateMethods)  
  508.   
  509. +(NSData *)baseEncode:(const voidvoid *)bytes  
  510.                length:(NSUInteger)length  
  511.               charset:(const charchar *)charset  
  512.                padded:(BOOL)padded;  
  513.   
  514. +(NSData *)baseDecode:(const voidvoid *)bytes  
  515.                length:(NSUInteger)length  
  516.               charset:(const char*)charset  
  517.        requirePadding:(BOOL)requirePadding;  
  518.   
  519. +(NSUInteger)baseEncode:(const charchar *)srcBytes  
  520.                  srcLen:(NSUInteger)srcLen  
  521.               destBytes:(charchar *)destBytes  
  522.                 destLen:(NSUInteger)destLen  
  523.                 charset:(const charchar *)charset  
  524.                  padded:(BOOL)padded;  
  525.   
  526. +(NSUInteger)baseDecode:(const charchar *)srcBytes  
  527.                  srcLen:(NSUInteger)srcLen  
  528.               destBytes:(charchar *)destBytes  
  529.                 destLen:(NSUInteger)destLen  
  530.                 charset:(const charchar *)charset  
  531.          requirePadding:(BOOL)requirePadding;  
  532.   
  533. @end  
  534.   
  535.   
  536. @implementation GTMBase64  
  537.   
  538. //  
  539. // Standard Base64 (RFC) handling  
  540. //  
  541.   
  542. +(NSData *)encodeData:(NSData *)data {  
  543.     return [self baseEncode:[data bytes]  
  544.                      length:[data length]  
  545.                     charset:kBase64EncodeChars  
  546.                      padded:YES];  
  547. }  
  548.   
  549. +(NSData *)decodeData:(NSData *)data {  
  550.     return [self baseDecode:[data bytes]  
  551.                      length:[data length]  
  552.                     charset:kBase64DecodeChars  
  553.              requirePadding:YES];  
  554. }  
  555.   
  556. +(NSData *)encodeBytes:(const voidvoid *)bytes length:(NSUInteger)length {  
  557.     return [self baseEncode:bytes  
  558.                      length:length  
  559.                     charset:kBase64EncodeChars  
  560.                      padded:YES];  
  561. }  
  562.   
  563. +(NSData *)decodeBytes:(const voidvoid *)bytes length:(NSUInteger)length {  
  564.     return [self baseDecode:bytes  
  565.                      length:length  
  566.                     charset:kBase64DecodeChars  
  567.              requirePadding:YES];  
  568. }  
  569.   
  570. +(NSString *)stringByEncodingData:(NSData *)data {  
  571.     NSString *result = nil;  
  572.     NSData *converted = [self baseEncode:[data bytes]  
  573.                                   length:[data length]  
  574.                                  charset:kBase64EncodeChars  
  575.                                   padded:YES];  
  576.     if (converted) {  
  577.         result = [[[NSString alloc] initWithData:converted  
  578.                                         encoding:NSASCIIStringEncoding] autorelease];  
  579.     }  
  580.     return result;  
  581. }  
  582.   
  583. +(NSString *)stringByEncodingBytes:(const voidvoid *)bytes length:(NSUInteger)length {  
  584.     NSString *result = nil;  
  585.     NSData *converted = [self baseEncode:bytes  
  586.                                   length:length  
  587.                                  charset:kBase64EncodeChars  
  588.                                   padded:YES];  
  589.     if (converted) {  
  590.         result = [[[NSString alloc] initWithData:converted  
  591.                                         encoding:NSASCIIStringEncoding] autorelease];  
  592.     }  
  593.     return result;  
  594. }  
  595.   
  596. +(NSData *)decodeString:(NSString *)string {  
  597.     NSData *result = nil;  
  598.     NSData *data = [string dataUsingEncoding:NSASCIIStringEncoding];  
  599.     if (data) {  
  600.         result = [self baseDecode:[data bytes]  
  601.                            length:[data length]  
  602.                           charset:kBase64DecodeChars  
  603.                    requirePadding:YES];  
  604.     }  
  605.     return result;  
  606. }  
  607.   
  608. //  
  609. // Modified Base64 encoding so the results can go onto urls.  
  610. //  
  611. // The changes are in the characters generated and also the result isn't  
  612. // padded to a multiple of 4.  
  613. // Must use the matching call to encode/decode, won't interop with the  
  614. // RFC versions.  
  615. //  
  616.   
  617. +(NSData *)webSafeEncodeData:(NSData *)data  
  618.                       padded:(BOOL)padded {  
  619.     return [self baseEncode:[data bytes]  
  620.                      length:[data length]  
  621.                     charset:kWebSafeBase64EncodeChars  
  622.                      padded:padded];  
  623. }  
  624.   
  625. +(NSData *)webSafeDecodeData:(NSData *)data {  
  626.     return [self baseDecode:[data bytes]  
  627.                      length:[data length]  
  628.                     charset:kWebSafeBase64DecodeChars  
  629.              requirePadding:NO];  
  630. }  
  631.   
  632. +(NSData *)webSafeEncodeBytes:(const voidvoid *)bytes  
  633.                        length:(NSUInteger)length  
  634.                        padded:(BOOL)padded {  
  635.     return [self baseEncode:bytes  
  636.                      length:length  
  637.                     charset:kWebSafeBase64EncodeChars  
  638.                      padded:padded];  
  639. }  
  640.   
  641. +(NSData *)webSafeDecodeBytes:(const voidvoid *)bytes length:(NSUInteger)length {  
  642.     return [self baseDecode:bytes  
  643.                      length:length  
  644.                     charset:kWebSafeBase64DecodeChars  
  645.              requirePadding:NO];  
  646. }  
  647.   
  648. +(NSString *)stringByWebSafeEncodingData:(NSData *)data  
  649.                                   padded:(BOOL)padded {  
  650.     NSString *result = nil;  
  651.     NSData *converted = [self baseEncode:[data bytes]  
  652.                                   length:[data length]  
  653.                                  charset:kWebSafeBase64EncodeChars  
  654.                                   padded:padded];  
  655.     if (converted) {  
  656.         result = [[[NSString alloc] initWithData:converted  
  657.                                         encoding:NSASCIIStringEncoding] autorelease];  
  658.     }  
  659.     return result;  
  660. }  
  661.   
  662. +(NSString *)stringByWebSafeEncodingBytes:(const voidvoid *)bytes  
  663.                                    length:(NSUInteger)length  
  664.                                    padded:(BOOL)padded {  
  665.     NSString *result = nil;  
  666.     NSData *converted = [self baseEncode:bytes  
  667.                                   length:length  
  668.                                  charset:kWebSafeBase64EncodeChars  
  669.                                   padded:padded];  
  670.     if (converted) {  
  671.         result = [[[NSString alloc] initWithData:converted  
  672.                                         encoding:NSASCIIStringEncoding] autorelease];  
  673.     }  
  674.     return result;  
  675. }  
  676.   
  677. +(NSData *)webSafeDecodeString:(NSString *)string {  
  678.     NSData *result = nil;  
  679.     NSData *data = [string dataUsingEncoding:NSASCIIStringEncoding];  
  680.     if (data) {  
  681.         result = [self baseDecode:[data bytes]  
  682.                            length:[data length]  
  683.                           charset:kWebSafeBase64DecodeChars  
  684.                    requirePadding:NO];  
  685.     }  
  686.     return result;  
  687. }  
  688.   
  689. // David Lee new added function  
  690. /// Returns:  
  691. // A new autoreleased NSString with Base64 encoded NSString  
  692. +(NSString *)stringByBase64String:(NSString *)base64String  
  693. {  
  694.     NSString *sourceString = [[[NSString alloc] initWithData:[GTMBase64 decodeData:[base64String dataUsingEncoding:NSUTF8StringEncoding allowLossyConversion:NO]] encoding:NSUTF8StringEncoding] autorelease];  
  695.     return sourceString;  
  696. }  
  697.   
  698. // David Lee new added function  
  699. /// Returns:  
  700. // A new autoreleased Base64 encoded NSString with NSString  
  701. +(NSString *)base64StringBystring:(NSString *)string  
  702. {  
  703.     NSString *base64String = [[[NSString alloc] initWithData:[GTMBase64 encodeData:[string dataUsingEncoding:NSUTF8StringEncoding allowLossyConversion:NO]] encoding:NSUTF8StringEncoding] autorelease];  
  704.     return base64String;  
  705. }  
  706.   
  707. @end  
  708.   
  709. @implementation GTMBase64 (PrivateMethods)  
  710.   
  711. //  
  712. // baseEncode:length:charset:padded:  
  713. //  
  714. // Does the common lifting of creating the dest NSData.  it creates & sizes the  
  715. // data for the results.  |charset| is the characters to use for the encoding  
  716. // of the data.  |padding| controls if the encoded data should be padded to a  
  717. // multiple of 4.  
  718. //  
  719. // Returns:  
  720. //   an autorelease NSData with the encoded data, nil if any error.  
  721. //  
  722. +(NSData *)baseEncode:(const voidvoid *)bytes  
  723.                length:(NSUInteger)length  
  724.               charset:(const charchar *)charset  
  725.                padded:(BOOL)padded {  
  726.     // how big could it be?  
  727.     NSUInteger maxLength = CalcEncodedLength(length, padded);  
  728.     // make space  
  729.     NSMutableData *result = [NSMutableData data];  
  730.     [result setLength:maxLength];  
  731.     // do it  
  732.     NSUInteger finalLength = [self baseEncode:bytes  
  733.                                        srcLen:length  
  734.                                     destBytes:[result mutableBytes]  
  735.                                       destLen:[result length]  
  736.                                       charset:charset  
  737.                                        padded:padded];  
  738.     if (finalLength) {  
  739.         NSAssert(finalLength == maxLength, @"how did we calc the length wrong?");  
  740.     } else {  
  741.         // shouldn't happen, this means we ran out of space  
  742.         result = nil;  
  743.     }  
  744.     return result;  
  745. }  
  746.   
  747. //  
  748. // baseDecode:length:charset:requirePadding:  
  749. //  
  750. // Does the common lifting of creating the dest NSData.  it creates & sizes the  
  751. // data for the results.  |charset| is the characters to use for the decoding  
  752. // of the data.  
  753. //  
  754. // Returns:  
  755. //   an autorelease NSData with the decoded data, nil if any error.  
  756. //  
  757. //  
  758. +(NSData *)baseDecode:(const voidvoid *)bytes  
  759.                length:(NSUInteger)length  
  760.               charset:(const charchar *)charset  
  761.        requirePadding:(BOOL)requirePadding {  
  762.     // could try to calculate what it will end up as  
  763.     NSUInteger maxLength = GuessDecodedLength(length);  
  764.     // make space  
  765.     NSMutableData *result = [NSMutableData data];  
  766.     [result setLength:maxLength];  
  767.     // do it  
  768.     NSUInteger finalLength = [self baseDecode:bytes  
  769.                                        srcLen:length  
  770.                                     destBytes:[result mutableBytes]  
  771.                                       destLen:[result length]  
  772.                                       charset:charset  
  773.                                requirePadding:requirePadding];  
  774.     if (finalLength) {  
  775.         if (finalLength != maxLength) {  
  776.             // resize down to how big it was  
  777.             [result setLength:finalLength];  
  778.         }  
  779.     } else {  
  780.         // either an error in the args, or we ran out of space  
  781.         result = nil;  
  782.     }  
  783.     return result;  
  784. }  
  785.   
  786. //  
  787. // baseEncode:srcLen:destBytes:destLen:charset:padded:  
  788. //  
  789. // Encodes the buffer into the larger.  returns the length of the encoded  
  790. // data, or zero for an error.  
  791. // |charset| is the characters to use for the encoding  
  792. // |padded| tells if the result should be padded to a multiple of 4.  
  793. //  
  794. // Returns:  
  795. //   the length of the encoded data.  zero if any error.  
  796. //  
  797. +(NSUInteger)baseEncode:(const charchar *)srcBytes  
  798.                  srcLen:(NSUInteger)srcLen  
  799.               destBytes:(charchar *)destBytes  
  800.                 destLen:(NSUInteger)destLen  
  801.                 charset:(const charchar *)charset  
  802.                  padded:(BOOL)padded {  
  803.     if (!srcLen || !destLen || !srcBytes || !destBytes) {  
  804.         return 0;  
  805.     }  
  806.       
  807.     charchar *curDest = destBytes;  
  808.     const unsigned charchar *curSrc = (const unsigned charchar *)(srcBytes);  
  809.       
  810.     // Three bytes of data encodes to four characters of cyphertext.  
  811.     // So we can pump through three-byte chunks atomically.  
  812.     while (srcLen > 2) {  
  813.         // space?  
  814.         NSAssert(destLen >= 4@"our calc for encoded length was wrong");  
  815.         curDest[0] = charset[curSrc[0] >> 2];  
  816.         curDest[1] = charset[((curSrc[0] & 0x03) << 4) + (curSrc[1] >> 4)];  
  817.         curDest[2] = charset[((curSrc[1] & 0x0f) << 2) + (curSrc[2] >> 6)];  
  818.         curDest[3] = charset[curSrc[2] & 0x3f];  
  819.           
  820.         curDest += 4;  
  821.         curSrc += 3;  
  822.         srcLen -= 3;  
  823.         destLen -= 4;  
  824.     }  
  825.       
  826.     // now deal with the tail (<=2 bytes)  
  827.     switch (srcLen) {  
  828.         case 0:  
  829.             // Nothing left; nothing more to do.  
  830.             break;  
  831.         case 1:  
  832.             // One byte left: this encodes to two characters, and (optionally)  
  833.             // two pad characters to round out the four-character cypherblock.  
  834.             NSAssert(destLen >= 2@"our calc for encoded length was wrong");  
  835.             curDest[0] = charset[curSrc[0] >> 2];  
  836.             curDest[1] = charset[(curSrc[0] & 0x03) << 4];  
  837.             curDest += 2;  
  838.             destLen -= 2;  
  839.             if (padded) {  
  840.                 NSAssert(destLen >= 2@"our calc for encoded length was wrong");  
  841.                 curDest[0] = kBase64PaddingChar;  
  842.                 curDest[1] = kBase64PaddingChar;  
  843.                 curDest += 2;  
  844.             }  
  845.             break;  
  846.         case 2:  
  847.             // Two bytes left: this encodes to three characters, and (optionally)  
  848.             // one pad character to round out the four-character cypherblock.  
  849.             NSAssert(destLen >= 3@"our calc for encoded length was wrong");  
  850.             curDest[0] = charset[curSrc[0] >> 2];  
  851.             curDest[1] = charset[((curSrc[0] & 0x03) << 4) + (curSrc[1] >> 4)];  
  852.             curDest[2] = charset[(curSrc[1] & 0x0f) << 2];  
  853.             curDest += 3;  
  854.             destLen -= 3;  
  855.             if (padded) {  
  856.                 NSAssert(destLen >= 1@"our calc for encoded length was wrong");  
  857.                 curDest[0] = kBase64PaddingChar;  
  858.                 curDest += 1;  
  859.             }  
  860.             break;  
  861.     }  
  862.     // return the length  
  863.     return (curDest - destBytes);  
  864. }  
  865.   
  866. //  
  867. // baseDecode:srcLen:destBytes:destLen:charset:requirePadding:  
  868. //  
  869. // Decodes the buffer into the larger.  returns the length of the decoded  
  870. // data, or zero for an error.  
  871. // |charset| is the character decoding buffer to use  
  872. //  
  873. // Returns:  
  874. //   the length of the encoded data.  zero if any error.  
  875. //  
  876. +(NSUInteger)baseDecode:(const charchar *)srcBytes  
  877.                  srcLen:(NSUInteger)srcLen  
  878.               destBytes:(charchar *)destBytes  
  879.                 destLen:(NSUInteger)destLen  
  880.                 charset:(const charchar *)charset  
  881.          requirePadding:(BOOL)requirePadding {  
  882.     if (!srcLen || !destLen || !srcBytes || !destBytes) {  
  883.         return 0;  
  884.     }  
  885.       
  886.     int decode;  
  887.     NSUInteger destIndex = 0;  
  888.     int state = 0;  
  889.     char ch = 0;  
  890.     while (srcLen-- && (ch = *srcBytes++) != 0)  {  
  891.         if (IsSpace(ch))  // Skip whitespace  
  892.             continue;  
  893.           
  894.         if (ch == kBase64PaddingChar)  
  895.             break;  
  896.           
  897.         decode = charset[(unsigned int)ch];  
  898.         if (decode == kBase64InvalidChar)  
  899.             return 0;  
  900.           
  901.         // Four cyphertext characters decode to three bytes.  
  902.         // Therefore we can be in one of four states.  
  903.         switch (state) {  
  904.             case 0:  
  905.                 // We're at the beginning of a four-character cyphertext block.  
  906.                 // This sets the high six bits of the first byte of the  
  907.                 // plaintext block.  
  908.                 NSAssert(destIndex < destLen, @"our calc for decoded length was wrong");  
  909.                 destBytes[destIndex] = decode << 2;  
  910.                 state = 1;  
  911.                 break;  
  912.             case 1:  
  913.                 // We're one character into a four-character cyphertext block.  
  914.                 // This sets the low two bits of the first plaintext byte,  
  915.                 // and the high four bits of the second plaintext byte.  
  916.                 NSAssert((destIndex+1) < destLen, @"our calc for decoded length was wrong");  
  917.                 destBytes[destIndex] |= decode >> 4;  
  918.                 destBytes[destIndex+1] = (decode & 0x0f) << 4;  
  919.                 destIndex++;  
  920.                 state = 2;  
  921.                 break;  
  922.             case 2:  
  923.                 // We're two characters into a four-character cyphertext block.  
  924.                 // This sets the low four bits of the second plaintext  
  925.                 // byte, and the high two bits of the third plaintext byte.  
  926.                 // However, if this is the end of data, and those two  
  927.                 // bits are zero, it could be that those two bits are  
  928.                 // leftovers from the encoding of data that had a length  
  929.                 // of two mod three.  
  930.                 NSAssert((destIndex+1) < destLen, @"our calc for decoded length was wrong");  
  931.                 destBytes[destIndex] |= decode >> 2;  
  932.                 destBytes[destIndex+1] = (decode & 0x03) << 6;  
  933.                 destIndex++;  
  934.                 state = 3;  
  935.                 break;  
  936.             case 3:  
  937.                 // We're at the last character of a four-character cyphertext block.  
  938.                 // This sets the low six bits of the third plaintext byte.  
  939.                 NSAssert(destIndex < destLen, @"our calc for decoded length was wrong");  
  940.                 destBytes[destIndex] |= decode;  
  941.                 destIndex++;  
  942.                 state = 0;  
  943.                 break;  
  944.         }  
  945.     }  
  946.       
  947.     // We are done decoding Base-64 chars.  Let's see if we ended  
  948.     //      on a byte boundary, and/or with erroneous trailing characters.  
  949.     if (ch == kBase64PaddingChar) {               // We got a pad char  
  950.         if ((state == 0) || (state == 1)) {  
  951.             return 0;  // Invalid '=' in first or second position  
  952.         }  
  953.         if (srcLen == 0) {  
  954.             if (state == 2) { // We run out of input but we still need another '='  
  955.                 return 0;  
  956.             }  
  957.             // Otherwise, we are in state 3 and only need this '='  
  958.         } else {  
  959.             if (state == 2) {  // need another '='  
  960.                 while ((ch = *srcBytes++) && (srcLen-- > 0)) {  
  961.                     if (!IsSpace(ch))  
  962.                         break;  
  963.                 }  
  964.                 if (ch != kBase64PaddingChar) {  
  965.                     return 0;  
  966.                 }  
  967.             }  
  968.             // state = 1 or 2, check if all remain padding is space  
  969.             while ((ch = *srcBytes++) && (srcLen-- > 0)) {  
  970.                 if (!IsSpace(ch)) {  
  971.                     return 0;  
  972.                 }  
  973.             }  
  974.         }  
  975.     } else {  
  976.         // We ended by seeing the end of the string.  
  977.           
  978.         if (requirePadding) {  
  979.             // If we require padding, then anything but state 0 is an error.  
  980.             if (state != 0) {  
  981.                 return 0;  
  982.             }  
  983.         } else {  
  984.             // Make sure we have no partial bytes lying around.  Note that we do not  
  985.             // require trailing '=', so states 2 and 3 are okay too.  
  986.             if (state == 1) {  
  987.                 return 0;  
  988.             }  
  989.         }  
  990.     }  
  991.       
  992.     // If then next piece of output was valid and got written to it means we got a  
  993.     // very carefully crafted input that appeared valid but contains some trailing  
  994.     // bits past the real length, so just toss the thing.  
  995.     if ((destIndex < destLen) &&  
  996.         (destBytes[destIndex] != 0)) {  
  997.         return 0;  
  998.     }  
  999.       
  1000.     return destIndex;  
  1001. }  
  1002.   
  1003. @end  


 

注:加密完后的字符串最好去下空格,防止网页被转码时空格影响解密


以上代码参考以下地址收集整理修改:

http://zxs19861202.iteye.com/blog/1980655              Android、iPhone和Java三个平台一致的加密方法

http://blog.sina.com.cn/s/blog_ad4920b70101lqqy.html   PHP的3DES加解密类 兼容JAVA

https://github.com/isaced/GTMBase64     ios 字符串的base64编解码


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值