Table des matières
前言
AES规则
AES加密算法
加密算法
解密算法
写在最后
关注我
Swift/ObjC技术群一:324400294(已满)
Swift/ObjC技术群二:494669518
ObjC/Swift高级群:461252383(注明年限,新手勿扰)
支持并捐助
Maison développement back-end tutoriel php iOS与PHP/Android AES128 ECB NoPadding加密

iOS与PHP/Android AES128 ECB NoPadding加密

Jun 20, 2016 pm 12:39 PM

来自: http://www.henishuo.com/ios-aes128-ecb-nopadding/

前言

谈谈AES加密,网上有很多的版本,当我没有真正在加密安全问题前,总以为百度出来某个AES加密算法就可以直接使用,实际上当我真正要做加密时,遇到了很多的坑,原来不是拿过来就能用的。写下本篇文章,记录下曾经遇到的坑,严防以后再出现同样的坑。

AES规则

原输入数据不够16字节的整数位时,就要补齐。因此就会有padding,若使用不同的padding,那么加密出来的结果也会不一样。

AES加密算法

苹果提供给我们的API只有这一个函数用来加密或者解密:

 CCCryptorStatus CCCrypt(    CCOperation op,        /* kCCEncrypt, etc. */    CCAlgorithm alg,        /* kCCAlgorithmAES128, etc. */    CCOptions options,      /* kCCOptionPKCS7Padding, etc. */    const void *key,    size_tkeyLength,    const void *iv,        /* optional initialization vector */    const void *dataIn,    /* optional per op and alg */    size_tdataInLength,    void *dataOut,          /* data RETURNED here */    size_tdataOutAvailable,    size_t*dataOutMoved)    __OSX_AVAILABLE_STARTING(__MAC_10_4, __IPHONE_2_0); 
Copier après la connexion

  • 其中第一个 CCOperation 只有两个值,要么是 kCCEncrypt 表示加密,要么是 kCCDecrypt 表示解密。
  • 第二个参数表示加密的算法,它只有以下向种类型:

 enum {    kCCAlgorithmAES128 = 0,    kCCAlgorithmAES = 0,    kCCAlgorithmDES,    kCCAlgorithm3DES,          kCCAlgorithmCAST,          kCCAlgorithmRC4,    kCCAlgorithmRC2,      kCCAlgorithmBlowfish    };typedef uint32_tCCAlgorithm; 
Copier après la connexion

我们这里使用的是 kCCAlgorithmAES128 表示使用AES128位加密。

  • 第三个参数表示选项,这里使用的是 kCCOptionECBMode ,表示ECB:

 enum {    /* options for block ciphers */    kCCOptionPKCS7Padding  = 0x0001,    kCCOptionECBMode        = 0x0002    /* stream ciphers currently have no options */};typedef uint32_tCCOptions; 
Copier après la connexion

  • 第四个参数表示加密/解密的密钥。
  • 第五个参数keyLength表示密钥的长度。
  • 第六个参数iv是个固定值,通过直接使用密钥即可。大家一定要注视这个参数,如果安卓、服务端和iOS端不统一,那么加密结果就会不一样,解密可能能解出来,但是解密后在末尾会出现一些\0、\t之类的。
  • 第七个参数dataIn表示要加密/解密的数据。
  • 第八个参数dataInLength表示要加密/解密的数据的长度。
  • 第九个参数dataOut用于接收加密后/解密后的结果。
  • 第十个参数dataOutAvailable表示加密后/解密后的数据的长度。
  • 第十一个参数dataOutMoved表示实际加密/解密的数据的长度。(因为有补齐)

加密算法

依赖于第三方库: GTMBase64 ,这个库已经几年没有维护了,现在还是MRC版本,要使用请到GITHUB查看使用教程,那里有ARC接入说明:

 + (NSString *)hyb_AESEncrypt:(NSString *)plainTextpassword:(NSString *)key {  if (key == nil || (key.length != 16 && key.length != 32)) {    return nil;  }    char keyPtr[kCCKeySizeAES128+1];  memset(keyPtr, 0, sizeof(keyPtr));  [keygetCString:keyPtrmaxLength:sizeof(keyPtr)encoding:NSUTF8StringEncoding];      char ivPtr[kCCBlockSizeAES128+1];  memset(ivPtr, 0, sizeof(ivPtr));  [keygetCString:ivPtrmaxLength:sizeof(ivPtr)encoding:NSUTF8StringEncoding];    NSData* data = [plainTextdataUsingEncoding:NSUTF8StringEncoding];  NSUInteger dataLength = [datalength];    int diff = kCCKeySizeAES128 - (dataLength % kCCKeySizeAES128);  unsigned long newSize = 0;    if(diff > 0) {    newSize = dataLength + diff;  }    char dataPtr[newSize];  memcpy(dataPtr, [databytes], [datalength]);  for(int i = 0; i < diff; i++) {    // 这里是关键,这里是使用NoPadding的    dataPtr[i + dataLength] = 0x0000;  }    size_tbufferSize = newSize + kCCBlockSizeAES128;  void *buffer = malloc(bufferSize);  memset(buffer, 0, bufferSize);    size_tnumBytesCrypted = 0;    CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt,                                        kCCAlgorithmAES128,                                        kCCOptionECBMode,                                        [keyUTF8String],                                        kCCKeySizeAES128,                                        ivPtr,                                        dataPtr,                                        sizeof(dataPtr),                                        buffer,                                        bufferSize,                                        &numBytesCrypted);    if (cryptStatus == kCCSuccess) {    NSData *resultData = [NSDatadataWithBytesNoCopy:bufferlength:numBytesCrypted];    return [GTMBase64stringByEncodingData:resultData];  }    free(buffer);  return nil;} 
Copier après la connexion

对于加密算法,大家一定要注意,保证iOS、安卓、服务端的加密规则是一定的,建议统一使用No Padding的,这里使用No Padding是这样的:

 for(int i = 0; i < diff; i++) {    // 这里是关键,这里是使用NoPadding的    dataPtr[i + dataLength] = 0x0000;} 
Copier après la connexion

其实所谓Padding就是指在位数不够需要补齐时,使用什么来填充,而No Padding就是使用16个0,对应0x0000.如果三端不统一,加密出来就算能解密,也会出现一些奇怪的字符,甚至会有部分乱码。

另外,这里使用的是 kCCOptionECBMode ,也就是ECB。在安卓端和PHP端,也得使用ECB。在调试过程中,发现PHP使用CBC解密不了IOS端的。于是改成了使用ECB。

解密算法

依赖于第三方库: GTMBase64 ,这个库已经几年没有维护了,现在还是MRC版本,要使用请到GITHUB查看使用教程,那里有ARC接入说明:

 + (NSString *)hyb_AESDecrypt:(NSString *)encryptTextpassword:(NSString *)key {  if (key == nil || (key.length != 16 && key.length != 32)) {    return nil;  }    char keyPtr[kCCKeySizeAES128 + 1];  memset(keyPtr, 0, sizeof(keyPtr));  [keygetCString:keyPtrmaxLength:sizeof(keyPtr)encoding:NSUTF8StringEncoding];    char ivPtr[kCCBlockSizeAES128 + 1];  memset(ivPtr, 0, sizeof(ivPtr));  [keygetCString:ivPtrmaxLength:sizeof(ivPtr)encoding:NSUTF8StringEncoding];    NSData *data = [GTMBase64decodeData:[encryptTextdataUsingEncoding:NSUTF8StringEncoding]];  NSUInteger dataLength = [datalength];  size_tbufferSize = dataLength + kCCBlockSizeAES128;  void *buffer = malloc(bufferSize);    size_tnumBytesCrypted = 0;  CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt,                                        kCCAlgorithmAES128,                                        kCCOptionECBMode,                                        [keyUTF8String],                                        kCCBlockSizeAES128,                                        ivPtr,                                        [databytes],                                        dataLength,                                        buffer,                                        bufferSize,                                        &numBytesCrypted);  if (cryptStatus == kCCSuccess) {    NSData *resultData = [NSDatadataWithBytesNoCopy:bufferlength:numBytesCrypted];        NSString *decoded=[[NSString alloc]initWithData:resultDataencoding:NSUTF8StringEncoding];    return decoded;  }    free(buffer);  return nil;} 
Copier après la connexion

解密时也得跟加密一样指定为ECB,否则解出来会出现乱码,或者末尾会出现\0、\t之类的符号。

写在最后

开发中总会遇到各种坑,网上查了很多的资料,但是终究没有说明解决的办法,而是只将自己的代码放出来。对于刚接触这方面知识的开发人员来说,是很懵懂的。甚至很多新手会觉得系统就是这样的,我也没办法。其实总会有解决办法的,关键在于与其他各端统一连调。

关注我

Swift/ObjC技术群一:324400294(已满)

Swift/ObjC技术群二:494669518

ObjC/Swift高级群:461252383(注明年限,新手勿扰)

关注微信公众号: iOSDevShares

关注新浪微博账号:标哥Jacky

标哥的GITHUB地址: CoderJackyHuang

支持并捐助

如果您觉得文章对您很有帮忙,希望得到您的支持。您的捐肋将会给予我最大的鼓励,感谢您的支持!

支付宝捐助 微信捐助
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn

Outils d'IA chauds

Undresser.AI Undress

Undresser.AI Undress

Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover

AI Clothes Remover

Outil d'IA en ligne pour supprimer les vêtements des photos.

Undress AI Tool

Undress AI Tool

Images de déshabillage gratuites

Clothoff.io

Clothoff.io

Dissolvant de vêtements AI

AI Hentai Generator

AI Hentai Generator

Générez AI Hentai gratuitement.

Outils chauds

Bloc-notes++7.3.1

Bloc-notes++7.3.1

Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise

SublimeText3 version chinoise

Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1

Envoyer Studio 13.0.1

Puissant environnement de développement intégré PHP

Dreamweaver CS6

Dreamweaver CS6

Outils de développement Web visuel

SublimeText3 version Mac

SublimeText3 version Mac

Logiciel d'édition de code au niveau de Dieu (SublimeText3)

Expliquez les jetons Web JSON (JWT) et leur cas d'utilisation dans les API PHP. Expliquez les jetons Web JSON (JWT) et leur cas d'utilisation dans les API PHP. Apr 05, 2025 am 12:04 AM

JWT est une norme ouverte basée sur JSON, utilisée pour transmettre en toute sécurité des informations entre les parties, principalement pour l'authentification de l'identité et l'échange d'informations. 1. JWT se compose de trois parties: en-tête, charge utile et signature. 2. Le principe de travail de JWT comprend trois étapes: la génération de JWT, la vérification de la charge utile JWT et l'analyse. 3. Lorsque vous utilisez JWT pour l'authentification en PHP, JWT peut être généré et vérifié, et les informations sur le rôle et l'autorisation des utilisateurs peuvent être incluses dans l'utilisation avancée. 4. Les erreurs courantes incluent une défaillance de vérification de signature, l'expiration des jetons et la charge utile surdimensionnée. Les compétences de débogage incluent l'utilisation des outils de débogage et de l'exploitation forestière. 5. L'optimisation des performances et les meilleures pratiques incluent l'utilisation des algorithmes de signature appropriés, la définition des périodes de validité raisonnablement,

Décrivez les principes solides et comment ils s'appliquent au développement de PHP. Décrivez les principes solides et comment ils s'appliquent au développement de PHP. Apr 03, 2025 am 12:04 AM

L'application du principe solide dans le développement de PHP comprend: 1. Principe de responsabilité unique (SRP): Chaque classe n'est responsable d'une seule fonction. 2. Principe ouvert et ferme (OCP): les changements sont réalisés par extension plutôt que par modification. 3. Principe de substitution de Lisch (LSP): les sous-classes peuvent remplacer les classes de base sans affecter la précision du programme. 4. Principe d'isolement d'interface (ISP): utilisez des interfaces à grain fin pour éviter les dépendances et les méthodes inutilisées. 5. Principe d'inversion de dépendance (DIP): les modules élevés et de bas niveau reposent sur l'abstraction et sont mis en œuvre par injection de dépendance.

Comment définir automatiquement les autorisations d'UnixSocket après le redémarrage du système? Comment définir automatiquement les autorisations d'UnixSocket après le redémarrage du système? Mar 31, 2025 pm 11:54 PM

Comment définir automatiquement les autorisations d'UnixSocket après le redémarrage du système. Chaque fois que le système redémarre, nous devons exécuter la commande suivante pour modifier les autorisations d'UnixSocket: sudo ...

Expliquez le concept de liaison statique tardive en PHP. Expliquez le concept de liaison statique tardive en PHP. Mar 21, 2025 pm 01:33 PM

L'article traite de la liaison statique tardive (LSB) dans PHP, introduite dans PHP 5.3, permettant une résolution d'exécution de la méthode statique nécessite un héritage plus flexible. Problème main: LSB vs polymorphisme traditionnel; Applications pratiques de LSB et perfo potentiel

Comment déboguer le mode CLI dans phpstorm? Comment déboguer le mode CLI dans phpstorm? Apr 01, 2025 pm 02:57 PM

Comment déboguer le mode CLI dans phpstorm? Lors du développement avec PHPStorm, nous devons parfois déboguer PHP en mode interface de ligne de commande (CLI) ...

Comment envoyer une demande post contenant des données JSON à l'aide de la bibliothèque Curl de PHP? Comment envoyer une demande post contenant des données JSON à l'aide de la bibliothèque Curl de PHP? Apr 01, 2025 pm 03:12 PM

Envoyant des données JSON à l'aide de la bibliothèque Curl de PHP dans le développement de PHP, il est souvent nécessaire d'interagir avec les API externes. L'une des façons courantes consiste à utiliser la bibliothèque Curl pour envoyer le post� ...

Caractéristiques de sécurité du cadre: protection contre les vulnérabilités. Caractéristiques de sécurité du cadre: protection contre les vulnérabilités. Mar 28, 2025 pm 05:11 PM

L'article traite des fonctionnalités de sécurité essentielles dans les cadres pour se protéger contre les vulnérabilités, notamment la validation des entrées, l'authentification et les mises à jour régulières.

See all articles