Swiftでアプリケーションを作成します。AES暗号化および復号化機能が必要です。別の.Netソリューションから暗号化されたデータを受け取りましたが、それを行うための何かが見つかりません。
これは私の.net暗号化です。
public static byte[] AES_Encrypt(byte[] bytesToBeEncrypted, byte[] passwordBytes)
{
byte[] encryptedBytes = null;
byte[] saltBytes = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 };
using (MemoryStream ms = new MemoryStream())
{
using (RijndaelManaged AES = new RijndaelManaged())
{
AES.KeySize = 256;
AES.BlockSize = 128;
var key = new Rfc2898DeriveBytes(passwordBytes, saltBytes, 1000);
AES.Key = key.GetBytes(AES.KeySize / 8);
AES.IV = key.GetBytes(AES.BlockSize / 8);
AES.Mode = CipherMode.CBC;
using (var cs = new CryptoStream(ms, AES.CreateEncryptor(), CryptoStreamMode.Write))
{
cs.Write(bytesToBeEncrypted, 0, bytesToBeEncrypted.Length);
cs.Close();
}
encryptedBytes = ms.ToArray();
}
}
return encryptedBytes;
}
Swiftで関数を解読する必要があります。
私は解決策を見つけました、それは良いライブラリです。
クロスプラットフォーム256ビットAES暗号化/復号化。
このプロジェクトには、すべてのプラットフォーム(C#、iOS、Android)で動作する256ビットAES暗号化の実装が含まれています。重要な目的の1つは、AESを簡単な実装ですべてのプラットフォームで動作させることです。
サポートされるプラットフォーム:iOS、Android、Windows(C#)。
CryptoSwift 例
Swift 2に更新
import Foundation
import CryptoSwift
extension String {
func aesEncrypt(key: String, iv: String) throws -> String{
let data = self.dataUsingEncoding(NSUTF8StringEncoding)
let enc = try AES(key: key, iv: iv, blockMode:.CBC).encrypt(data!.arrayOfBytes(), padding: PKCS7())
let encData = NSData(bytes: enc, length: Int(enc.count))
let base64String: String = encData.base64EncodedStringWithOptions(NSDataBase64EncodingOptions(rawValue: 0));
let result = String(base64String)
return result
}
func aesDecrypt(key: String, iv: String) throws -> String {
let data = NSData(base64EncodedString: self, options: NSDataBase64DecodingOptions(rawValue: 0))
let dec = try AES(key: key, iv: iv, blockMode:.CBC).decrypt(data!.arrayOfBytes(), padding: PKCS7())
let decData = NSData(bytes: dec, length: Int(dec.count))
let result = NSString(data: decData, encoding: NSUTF8StringEncoding)
return String(result!)
}
}
使用法:
let key = "bbC2H19lkVbQDfakxcrtNMQdd0FloLyw" // length == 32
let iv = "gqLOHUioQ0QjhuvI" // length == 16
let s = "string to encrypt"
let enc = try! s.aesEncrypt(key, iv: iv)
let dec = try! enc.aesDecrypt(key, iv: iv)
print(s) // string to encrypt
print("enc:\(enc)") // 2r0+KirTTegQfF4wI8rws0LuV8h82rHyyYz7xBpXIpM=
print("dec:\(dec)") // string to encrypt
print("\(s == dec)") // true
Iv(16)とキー(32)の長さが正しいことを確認すると、「ブロックサイズと初期化ベクトルは同じ長さでなければなりません!」エラー。
CryptoSwift 例
更新Swift 4。*
func aesEncrypt() throws -> String {
let encrypted = try AES(key: KEY, iv: IV, padding: .pkcs7).encrypt([UInt8](self.data(using: .utf8)!))
return Data(encrypted).base64EncodedString()
}
func aesDecrypt() throws -> String {
guard let data = Data(base64Encoded: self) else { return "" }
let decrypted = try AES(key: KEY, iv: IV, padding: .pkcs7).decrypt([UInt8](data))
return String(bytes: decrypted, encoding: .utf8) ?? self
}
SHSが提供するコードは機能しませんでしたが、これは明らかに機能しました(ブリッジヘッダーを使用しました:#import <CommonCrypto/CommonCrypto.h>
):
extension String {
func aesEncrypt(key:String, iv:String, options:Int = kCCOptionPKCS7Padding) -> String? {
if let keyData = key.data(using: String.Encoding.utf8),
let data = self.data(using: String.Encoding.utf8),
let cryptData = NSMutableData(length: Int((data.count)) + kCCBlockSizeAES128) {
let keyLength = size_t(kCCKeySizeAES128)
let operation: CCOperation = UInt32(kCCEncrypt)
let algoritm: CCAlgorithm = UInt32(kCCAlgorithmAES128)
let options: CCOptions = UInt32(options)
var numBytesEncrypted :size_t = 0
let cryptStatus = CCCrypt(operation,
algoritm,
options,
(keyData as NSData).bytes, keyLength,
iv,
(data as NSData).bytes, data.count,
cryptData.mutableBytes, cryptData.length,
&numBytesEncrypted)
if UInt32(cryptStatus) == UInt32(kCCSuccess) {
cryptData.length = Int(numBytesEncrypted)
let base64cryptString = cryptData.base64EncodedString(options: .lineLength64Characters)
return base64cryptString
}
else {
return nil
}
}
return nil
}
func aesDecrypt(key:String, iv:String, options:Int = kCCOptionPKCS7Padding) -> String? {
if let keyData = key.data(using: String.Encoding.utf8),
let data = NSData(base64Encoded: self, options: .ignoreUnknownCharacters),
let cryptData = NSMutableData(length: Int((data.length)) + kCCBlockSizeAES128) {
let keyLength = size_t(kCCKeySizeAES128)
let operation: CCOperation = UInt32(kCCDecrypt)
let algoritm: CCAlgorithm = UInt32(kCCAlgorithmAES128)
let options: CCOptions = UInt32(options)
var numBytesEncrypted :size_t = 0
let cryptStatus = CCCrypt(operation,
algoritm,
options,
(keyData as NSData).bytes, keyLength,
iv,
data.bytes, data.length,
cryptData.mutableBytes, cryptData.length,
&numBytesEncrypted)
if UInt32(cryptStatus) == UInt32(kCCSuccess) {
cryptData.length = Int(numBytesEncrypted)
let unencryptedMessage = String(data: cryptData as Data, encoding:String.Encoding.utf8)
return unencryptedMessage
}
else {
return nil
}
}
return nil
}
}
私のViewController
から:
let encoded = message.aesEncrypt(key: keyString, iv: iv)
let unencode = encoded?.aesDecrypt(key: keyString, iv: iv)
興味深い「純粋な」オープンソースライブラリがあります。
CryptoSwift: https://github.com/krzyzanowskim/CryptoSwift
サポート対象:AES-128、AES-192、AES-256、ChaCha20
AES復号化の例(プロジェクトのREADME.mdファイルから取得):
import CryptoSwift
let setup = (key: keyData, iv: ivData)
let decryptedAES = AES(setup).decrypt(encryptedData)
CommonCryptoを使用して、MihaelIsaev/HMAC.Swiftのコードから Easy to use Swift CommonCrypto HMACの実装 。この実装はBridging-Headerを使用せずに、モジュールファイルの作成。
AESEncryptおよびDecryptを使用するために、HAMC.Swiftの「extension String {」内に関数を直接追加しました。
func aesEncrypt(key:String, iv:String, options:Int = kCCOptionPKCS7Padding) -> String? {
if let keyData = key.dataUsingEncoding(NSUTF8StringEncoding),
data = self.dataUsingEncoding(NSUTF8StringEncoding),
cryptData = NSMutableData(length: Int((data.length)) + kCCBlockSizeAES128) {
let keyLength = size_t(kCCKeySizeAES128)
let operation: CCOperation = UInt32(kCCEncrypt)
let algoritm: CCAlgorithm = UInt32(kCCAlgorithmAES128)
let options: CCOptions = UInt32(options)
var numBytesEncrypted :size_t = 0
let cryptStatus = CCCrypt(operation,
algoritm,
options,
keyData.bytes, keyLength,
iv,
data.bytes, data.length,
cryptData.mutableBytes, cryptData.length,
&numBytesEncrypted)
if UInt32(cryptStatus) == UInt32(kCCSuccess) {
cryptData.length = Int(numBytesEncrypted)
let base64cryptString = cryptData.base64EncodedStringWithOptions(.Encoding64CharacterLineLength)
return base64cryptString
}
else {
return nil
}
}
return nil
}
func aesDecrypt(key:String, iv:String, options:Int = kCCOptionPKCS7Padding) -> String? {
if let keyData = key.dataUsingEncoding(NSUTF8StringEncoding),
data = NSData(base64EncodedString: self, options: .IgnoreUnknownCharacters),
cryptData = NSMutableData(length: Int((data.length)) + kCCBlockSizeAES128) {
let keyLength = size_t(kCCKeySizeAES128)
let operation: CCOperation = UInt32(kCCDecrypt)
let algoritm: CCAlgorithm = UInt32(kCCAlgorithmAES128)
let options: CCOptions = UInt32(options)
var numBytesEncrypted :size_t = 0
let cryptStatus = CCCrypt(operation,
algoritm,
options,
keyData.bytes, keyLength,
iv,
data.bytes, data.length,
cryptData.mutableBytes, cryptData.length,
&numBytesEncrypted)
if UInt32(cryptStatus) == UInt32(kCCSuccess) {
cryptData.length = Int(numBytesEncrypted)
let unencryptedMessage = String(data: cryptData, encoding:NSUTF8StringEncoding)
return unencryptedMessage
}
else {
return nil
}
}
return nil
}
関数は RNCryptor から取得されました。これは、ブリッジングヘッダーを使用せずに、ハッシュ関数と1つの単一ファイル「HMAC.Swift」に簡単に追加できました。これがSwiftハッシュとAES暗号化/復号化を必要とする開発者に役立つことを願っています。
下のようにAESDecryptを使用する例。
let iv = "AA-salt-BBCCDD--" // should be of 16 characters.
//here we are convert nsdata to String
let encryptedString = String(data: dataFromURL, encoding: NSUTF8StringEncoding)
//now we are decrypting
if let decryptedString = encryptedString?.aesDecrypt("12345678901234567890123456789012", iv: iv) // 32 char pass key
{
// Your decryptedString
}
CryptoSwiftは非常に興味深いプロジェクトですが、現時点ではAESの速度に制限があります。深刻な暗号化を行う必要がある場合は注意してください-CommonCryptoを実装する橋の痛みを経験する価値があるかもしれません。
PureSwift実装のためのMarcinへのBigUps
IOSまたはCryptoSwiftのCommonCryptoを外部ライブラリとして使用できます。以下の両方のツールを使用した実装があります。とはいえ、CCドキュメントではAESのモードを使用していないため、AESを使用したCommonCrypto出力をテストする必要があります。
CommonCrypto in Swift 4.2
import CommonCrypto func encrypt(data:Data)-> Data { return cryptCC(data:data、key:key、operation:kCCEncrypt) } func decrypt(data:Data)-> Data { return cryptCC(data:data、key:key、operation:kCCDecrypt) } private func cryptCC(data:Data、key:String operation:Int)-> Data { guard key.count == kCCKeySizeAES128 else { fatalError( "Key size failed!") } var ivBytes:[UInt8] var inBytes:[UInt8] var outLength:Int 操作== kCCEncrypt { ivBytes = [UInt8](繰り返し:0、カウント:kCCBlockSizeAES128) guard kCCSuccess == SecRandomCopyBytes (kSecRandomDefault、ivBytes.count、&ivBytes)else { fatalError( "IV creation failed!") } inB ytes = Array(data) outLength = data.count + kCCBlockSizeAES128 } else { ivBytes = Array(Array(data).dropLast(data.count) -kCCBlockSizeAES128)) inBytes = Array(Array(data).dropFirst(kCCBlockSizeAES128)) outLength = inBytes.count } var outBytes = [UInt8](繰り返し:0、カウント:outLength) var bytesMutated = 0 guard kCCSuccess == CCCrypt(CCOperation(operation)、CCAlgorithm (kCCAlgorithmAES128)、CCOptions(kCCOptionPKCS7Padding)、Array(key)、kCCKeySizeAES128、&ivBytes、&inBytes、inBytes.count、&outBytes、outLength、&bytesMutated)else { fatalError( "Cryptography operation \(operation)failed") } var outData = Data(bytes:&outBytes、count:bytesMutated) if operation == kCCEncrypt { ivBytes .append(contentsOf:Array(outDa ta)) outData = Data(bytes:ivBytes) } return outData }
CryptoSwift v0.14 in Swift 4.2
enum操作{ case encrypt case decrypt } private let keySizeAES128 = 16 private let aesBlockSize = 16 func encrypt(data:Data、key:String)-> Data { return crypt(data:data、key:key、operation :.encrypt) } func decrypt(data:Data、key:String)-> Data { return crypt(data:data、key:key 、操作:.decrypt) } private func crypt(data:Data、key:String、operation:Operation)-> Data { guard key.count == keySizeAES128 else { fatalError( "Key size failed!") } var outData:Data? = nil if operation == .encrypt { var ivBytes = [UInt8](繰り返し:0、カウント:aesBlockSize) guard 0 == SecRandomCopyBytes( kSecRandomDefault、ivBytes.count、&ivBytes)else { fatalError( "IV creation failed!") } do { let aes = try AES(key:Array(key.data(using:.utf8)!)、blockMode:CBC(iv:ivBytes)) let encrypted = try aes.encrypt(Array(data)) ivBytes.append(contentsOf:encrypted) outData = Data(bytes:ivBytes) } catch { print( "暗号化エラー:\(エラー) ") } } else { let ivBytes = Array(Array(data).dropLast(data.count-aesBlockSize)) let inBytes = Array(Array(data).dropFirst(aesBlockSize)) do { let aes = try AES(key:Array(key.data(using:.utf8)!)、blockMode:CBC(iv:ivBytes)) let decrypted = try aes.decrypt(inBytes) outData = Data(bytes:decrypted) } catch { print( "復号化エラー:\(error)") } } return outData! }
Swift4:
let key = "ccC2H19lDDbQDfakxcrtNMQdd0FloLGG" // length == 32
let iv = "ggGGHUiDD0Qjhuvv" // length == 16
func encryptFile(_ path: URL) -> Bool{
do{
let data = try Data.init(contentsOf: path)
let encodedData = try data.aesEncrypt(key: key, iv: iv)
try encodedData.write(to: path)
return true
}catch{
return false
}
}
func decryptFile(_ path: URL) -> Bool{
do{
let data = try Data.init(contentsOf: path)
let decodedData = try data.aesDecrypt(key: key, iv: iv)
try decodedData.write(to: path)
return true
}catch{
return false
}
}
**ポッドインストールCrypto Swift ** 1.ポッド 'CryptoSwift' #PodFileに追加2.ポッドインストール
import CryptoSwift
extension Data {
func aesEncrypt(key: String, iv: String) throws -> Data{
let encypted = try AES(key: key.bytes, blockMode: CBC(iv: iv.bytes), padding: .pkcs7).encrypt(self.bytes)
return Data(bytes: encypted)
}
func aesDecrypt(key: String, iv: String) throws -> Data {
let decrypted = try AES(key: key.bytes, blockMode: CBC(iv: iv.bytes), padding: .pkcs7).decrypt(self.bytes)
return Data(bytes: decrypted)
}
}
これはかなり古い投稿ですが、XCode 1 CommonCryptoモジュールが追加されたため、モジュールマップは必要ありません。また、Swift 5を使用すると、迷惑なキャストは不要です。
次のようなことができます:
func decrypt(_ data: Data, iv: Data, key: Data) throws -> String {
var buffer = [UInt8](repeating: 0, count: data.count + kCCBlockSizeAES128)
var bufferLen: Int = 0
let status = CCCrypt(
CCOperation(kCCDecrypt),
CCAlgorithm(kCCAlgorithmAES128),
CCOptions(kCCOptionPKCS7Padding),
[UInt8](key),
kCCBlockSizeAES128,
[UInt8](iv),
[UInt8](data),
data.count,
&buffer,
buffer.count,
&bufferLen
)
guard status == kCCSuccess,
let str = String(data: Data(bytes: buffer, count: bufferLen),
encoding: .utf8) else {
throw NSError(domain: "AES", code: -1, userInfo: nil)
}
return str
}
私のために働いている以下のコードで試してください。
AES暗号化
public static String getEncryptedString(String value) {
try {
byte[] key = your Key in byte array;
byte[] input = sault in byte array
return Base64.encodeToString(encrypt(value.getBytes("UTF-8"), key, input), Base64.DEFAULT);
} catch (UnsupportedEncodingException e) {
return "";
}
}
public static byte[] encrypt(byte[] data, byte[] key, byte[] ivs) {
try {
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES");
byte[] finalIvs = new byte[16];
int len = ivs.length > 16 ? 16 : ivs.length;
System.arraycopy(ivs, 0, finalIvs, 0, len);
IvParameterSpec ivps = new IvParameterSpec(finalIvs);
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivps);
return cipher.doFinal(data);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
AES解読
public static String decrypt(String encrypted) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException, UnsupportedEncodingException {
byte[] key = your Key in byte array;
byte[] input = sault in byte array
SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");
IvParameterSpec ivSpec = new IvParameterSpec(input);
Cipher ecipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
ecipher.init(Cipher.DECRYPT_MODE, skeySpec, ivSpec);
byte[] raw = Base64.decode(encrypted, Base64.DEFAULT);
byte[] originalBytes = ecipher.doFinal(raw);
String original = new String(originalBytes, "UTF8");
return original;
}
更新Swift 4.2
ここでは、たとえば、文字列をbase64encoded文字列に暗号化します。次に、同じものを解読して読み取り可能な文字列にします。 (これは入力文字列と同じです)。
私の場合、これを使用して文字列を暗号化し、QRコードに埋め込みます。次に、別のパーティがそれをスキャンし、同じものを復号化します。そのため、中級者はQRコードを理解できません。
ステップ1:文字列「Encrypt My Message 123」を暗号化します
ステップ2:暗号化されたbase64Encoded文字列:+ yvNjiD7F9/JKmqHTc/Mjg ==(QRコードに印刷されたものと同じ)
ステップ3:文字列「+ yvNjiD7F9/JKmqHTc/Mjg ==」をスキャンして解読する
ステップ4:最終結果-「メッセージ123を暗号化」
暗号化および復号化の機能
func encryption(stringToEncrypt: String) -> String{
let key = "MySecretPKey"
//let iv = "92c9d2c07a9f2e0a"
let data = stringToEncrypt.data(using: .utf8)
let keyD = key.data(using: .utf8)
let encr = (data as NSData?)!.aes128EncryptedData(withKey: keyD)
let base64String: String = (encr as NSData?)!.base64EncodedString(options: NSData.Base64EncodingOptions(rawValue: 0))
print(base64String)
return base64String
}
func decryption(encryptedString:String) -> String{
let key = "MySecretPKey"
//let iv = "92c9d2c07a9f2e0a"
let keyD = key.data(using: .utf8)
let decrpStr = NSData(base64Encoded: encryptedString, options: NSData.Base64DecodingOptions(rawValue: 0))
let dec = (decrpStr)!.aes128DecryptedData(withKey: keyD)
let backToString = String(data: dec!, encoding: String.Encoding.utf8)
print(backToString!)
return backToString!
}
使用法:
let enc = encryption(stringToEncrypt: "Encrypt My Message 123")
let decryptedString = decryption(encryptedString: enc)
print(decryptedString)
AES暗号化機能をサポートするクラス。これらはObjective-Cで記述されています。したがって、Swiftの場合、これらをサポートするにはブリッジヘッダーを使用する必要があります。
クラス名:NSData + AES.h
#import <Foundation/Foundation.h>
@interface NSData (AES)
- (NSData *)AES128EncryptedDataWithKey:(NSData *)key;
- (NSData *)AES128DecryptedDataWithKey:(NSData *)key;
- (NSData *)AES128EncryptedDataWithKey:(NSData *)key iv:(NSData *)iv;
- (NSData *)AES128DecryptedDataWithKey:(NSData *)key iv:(NSData *)iv;
@end
クラス名:NSData + AES.m
#import "NSData+AES.h"
#import <CommonCrypto/CommonCryptor.h>
@implementation NSData (AES)
- (NSData *)AES128EncryptedDataWithKey:(NSData *)key
{
return [self AES128EncryptedDataWithKey:key iv:nil];
}
- (NSData *)AES128DecryptedDataWithKey:(NSData *)key
{
return [self AES128DecryptedDataWithKey:key iv:nil];
}
- (NSData *)AES128EncryptedDataWithKey:(NSData *)key iv:(NSData *)iv
{
return [self AES128Operation:kCCEncrypt key:key iv:iv];
}
- (NSData *)AES128DecryptedDataWithKey:(NSData *)key iv:(NSData *)iv
{
return [self AES128Operation:kCCDecrypt key:key iv:iv];
}
- (NSData *)AES128Operation:(CCOperation)operation key:(NSData *)key iv:(NSData *)iv
{
NSUInteger dataLength = [self length];
size_t bufferSize = dataLength + kCCBlockSizeAES128;
void *buffer = malloc(bufferSize);
size_t numBytesEncrypted = 0;
CCCryptorStatus cryptStatus = CCCrypt(operation,
kCCAlgorithmAES128,
kCCOptionPKCS7Padding | kCCOptionECBMode,
key.bytes,
kCCBlockSizeAES128,
iv.bytes,
[self bytes],
dataLength,
buffer,
bufferSize,
&numBytesEncrypted);
if (cryptStatus == kCCSuccess) {
return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
}
free(buffer);
return nil;
}
@end
それがお役に立てば幸いです。
ありがとう!!!
copy&pasteこれらのメソッド(Swift 4 +):
class func encryptMessage(message: String, encryptionKey: String, iv: String) -> String? {
if let aes = try? AES(key: encryptionKey, iv: iv),
let encrypted = try? aes.encrypt(Array<UInt8>(message.utf8)) {
return encrypted.toHexString()
}
return nil
}
class func decryptMessage(encryptedMessage: String, encryptionKey: String, iv: String) -> String? {
if let aes = try? AES(key: encryptionKey, iv: iv),
let decrypted = try? aes.decrypt(Array<UInt8>(hex: encryptedMessage)) {
return String(data: Data(bytes: decrypted), encoding: .utf8)
}
return nil
}
例:
let encryptMessage = encryptMessage(message: "Hello World!", encryptionKey: "mykeymykeymykey1", iv: "myivmyivmyivmyiv")
// Output of encryptMessage is: 649849a5e700d540f72c4429498bf9f4
let decryptedMessage = decryptMessage(encryptedMessage: encryptMessage, encryptionKey: "mykeymykeymykey1", iv: "myivmyivmyivmyiv")
// Output of decryptedMessage is: Hello World!
encryptionKeyを忘れないでください&ivは16バイトでなければなりません。