ふるすたっくえんじにあっぽい人の日記

ASP .NET MVC (C#)、.NET Framework、iOS (Objective-c) アプリ、Androidアプリ (Java)、AWS、たまにLAMPとかプロジェクトマネジメントあたりのお話

【Objective-c】【C#】AESで暗号化・復号化

【追記】2014/10/20
これJava系(Android)とのやりとりでも使える・・・はずw

iOSASP .NET MVC Web API間で暗号化・復号化するときですねー
OpenSSL途中まで実装したけどAES128に妥協しました。はい。

とゆーことで、今日もさらしますよー

Objective-c

なお、base64エンコーディングは以下を使用させてもらっています。
そしてもちろんiOS側はてきとーでございます。嫌いなんじゃ。iOS
https://github.com/l4u/NSData-Base64

HttpSecurity.h

@interface HttpSecurity : NSObject

+ (NSString *)AESEncrypt:(NSString *)source key:(NSString *)key;
+ (NSString *)AESDecrypt:(NSString *)source key:(NSString *)key;

@end

HttpSecurity.m

#import "HttpSecurity.h"
#import <CommonCrypto/CommonCryptor.h>

@implementation HttpSecurity

NSString * const IV = @"!QAZS2WS9SX#CRFV";

+ (NSString *)AESEncrypt:(NSString *)source key:(NSString *)key
{
    char keyPtr[kCCKeySizeAES128 + 1];
    bzero(keyPtr, sizeof(keyPtr));
    [key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];

    char ivPtr[kCCBlockSizeAES128 + 1];
    bzero(ivPtr, sizeof(ivPtr));
    [IV getCString:ivPtr maxLength:sizeof(ivPtr) encoding:NSUTF8StringEncoding];

    NSData *sourceData = [source dataUsingEncoding:NSUTF8StringEncoding];
    size_t bufferSize = sourceData.length + kCCBlockSizeAES128;
    void *buffer = malloc(bufferSize);

    size_t numBytesEncrypted = 0;
    CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding,
                                          keyPtr, kCCBlockSizeAES128,
                                          ivPtr,
                                          sourceData.bytes, sourceData.length,
                                          buffer, bufferSize,
                                          &numBytesEncrypted);
    if (cryptStatus == kCCSuccess)
        return [[NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted] base64EncodedString];

    free(buffer);
    return nil;
}

+ (NSString *)AESDecrypt:(NSString *)source key:(NSString *)key
{
    char keyPtr[kCCKeySizeAES128 + 1];
    bzero(keyPtr, sizeof(keyPtr));
    [key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];

    char ivPtr[kCCBlockSizeAES128 + 1];
    bzero(ivPtr, sizeof(ivPtr));
    [IV getCString:ivPtr maxLength:sizeof(ivPtr) encoding:NSUTF8StringEncoding];

    NSData *sourceData = [NSData dataFromBase64String:source];
    size_t bufferSize = sourceData.length + kCCBlockSizeAES128;
    void *buffer = malloc(bufferSize);

    size_t numBytesEncrypted = 0;
    CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding,
                                          keyPtr, kCCBlockSizeAES128,
                                          ivPtr,
                                          sourceData.bytes, sourceData.length,
                                          buffer, bufferSize,
                                          &numBytesEncrypted);
    if (cryptStatus == kCCSuccess)
        return [[NSString alloc] initWithData:[NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted] encoding:NSUTF8StringEncoding];

    free(buffer);
    return nil;
}

@end

C#

public class WebSecurity
    {
        /// <summary>
        /// ブロックサイズ
        /// </summary>
        private const int aesBlockSize = 128;

        /// <summary>
        /// 鍵長
        /// </summary>
        private const int aesKeySize = 128;

        /// <summary>
        /// エンコーディング
        /// </summary>
        private static Encoding aesEncoding = Encoding.UTF8;

        /// <summary>
        /// 初期ベクタ
        /// </summary>
        private const string aesIV = "!QAZS2WS9SX#CRFV";

        /// <summary>
        /// 文字列を指定した鍵で暗号化
        /// </summary>
        /// <param name="source">暗号対象文字列</param>
        /// <param name="key">鍵</param>
        public static string AesEncrypt(string source, string key)
        {
            using (var provider = CreateAesProvider(key))
            {
                var sourceBytes = aesEncoding.GetBytes(source);
                using (var encryptor = provider.CreateEncryptor())
                {
                    var retBytes = encryptor.TransformFinalBlock(sourceBytes, 0, sourceBytes.Length);
                    return Convert.ToBase64String(retBytes);
                }
            }
        }

        /// <summary>
        /// 指定した鍵で復号化
        /// </summary>
        /// <param name="source">復号対象文字列</param>
        /// <param name="key">鍵</param>
        public static string AesDecrypt(string source, string key)
        {
            using (var provider = CreateAesProvider(key))
            {
                var sourceBytes = Convert.FromBase64String(source);
                using (var decryptor = provider.CreateDecryptor())
                {
                    var retBytes = decryptor.TransformFinalBlock(sourceBytes, 0, sourceBytes.Length);
                    return aesEncoding.GetString(retBytes);
                }
            }
        }

        /// <summary>
        /// AESプロバイダー生成
        /// </summary>
        /// <param name="key">鍵</param>
        private static AesCryptoServiceProvider CreateAesProvider(string key)
        {
            var provider = new AesCryptoServiceProvider();
            provider.BlockSize = aesBlockSize;
            provider.KeySize = aesKeySize;
            provider.IV = aesEncoding.GetBytes(aesIV);
            provider.Key = aesEncoding.GetBytes(key);
            provider.Mode = CipherMode.CBC;
            provider.Padding = PaddingMode.PKCS7;
            return provider;
        }
    }