AES Шифрование и Дешифрование
Я пишу приложение быстро, мне нужна функциональность AES Encrypt и Decrypt, я получил зашифрованные данные из другого решения.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.
9 ответов
Я нашел решение, это хорошая библиотека.
Кроссплатформенное 256-битное шифрование / дешифрование AES.
Этот проект содержит реализацию 256-битного шифрования AES, которое работает на всех платформах (C#, iOS, Android). Одна из ключевых задач - заставить 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: Data(decrypted).bytes, encoding: .utf8) ?? "Could not decrypt"
}
Код, предоставленный SHS, не работал для меня, но этот, очевидно, работал (я использовал Bridging Header: #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 = Cipher.AES(setup).decrypt(encryptedData)
Я использовал CommonCrypto для генерации Hash с помощью кода MihaelIsaev/HMAC.swift от Easy для использования Swift-реализации CommonCrypto HMAC. Эта реализация без использования Bridging-Header с созданием файла модуля.
Теперь, чтобы использовать AESEncrypt и Decrypt, я непосредственно добавил функции внутри "extension String {" в HAMC.swift.
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. Это было простое добавление в функции хеширования и в один файл "HMAC.swift", без использования Bridging-header. Я надеюсь, что это будет полезно для разработчиков в быстрой, требующей хеширования и шифрования / дешифрования 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.
BigUps для Marcin для реализации pureSwift
Вы можете использовать CommonCrypto из iOS или CryptoSwift в качестве внешней библиотеки. Ниже приведены реализации с обоими инструментами. Тем не менее, выход CommonCrypto с AES должен быть протестирован, так как в документации CC не ясно, какой режим AES он использует.
CommonCrypto в Swift 4.2
импорт CommonCrypto func encrypt(данные: данные) -> данные { возврат cryptCC (данные: данные, ключ: ключ, операция: kCCEncrypt) } функция дешифрования (данные: данные) -> данные { возврат cryptCC (данные: данные, ключ: ключ, операция: kCCDecrypt) } private func cryptCC(данные: данные, ключ: операция с строками: Int) -> данные { guard key.count == kCCKeySizeAES128 else { fatalError("Ошибка ключа!") } var ivBytes: [UInt8] var inBytes: [UInt8] var outLength: Int если операция == kCCEncrypt { ivBytes = [UInt8](повтор: 0, количество: kCCBlockSizeAES128) guard kCCSuccess == SecRandomCopyBytes(kSecRandomDefault, ivBytes.count и ivBytes) else { fatalError("Создание IV не удалось!") } inBytes = Array(data) outLength = data.count + kCCBlockSizeAES128 } еще { ivBytes = Array(Array(data).dropLast(data.count - kCCBlockSizeAES128)) inBytes = Array(Array(data).dropFirst(kCCBlockSizeAES128)) outLength = inBytes.count } var outBytes = [UInt8](повтор: 0, count: outLength) var bytesMutated = 0 guard kCCSuccess == CCCrypt(CCOperation(операция), CCAlgorithm(kCCAlgorithmAES128), CCOptions(kCCOptionPKCS7Padding), Массив (ключ), kCCKeySizeAES128, &ivBytes, &inBytes, inBytes.count, &outMytested, &outBytested fatalError ("Ошибка операции шифрования \ (операция)") } var outData = Data (bytes: &outBytes, count: bytesMutated) если операция == kCCEncrypt { ivBytes.append (contentsOf: Array (outData)) outData = Data (байты: ivBytes) } вернуть outData }
CryptoSwift v0.14 в Swift 4.2
enum Operation { шифрование дела расшифровка дела } private let keySizeAES128 = 16 private let aesBlockSize = 16 func encrypt(данные: данные, ключ: строка) -> данные { возвратный крипт (данные: данные, ключ: ключ, операция: .encrypt) } функция дешифрования (данные: данные, ключ: строка) -> данные { возвратный крипт (данные: данные, ключ: ключ, операция: .decrypt) } частный крипт функции (данные: данные, ключ: строка, операция: операция) -> данные { guard key.count == keySizeAES128 else { fatalError("Ошибка ключа!") } var outData: данные? = ноль если операция == .encrypt { var ivBytes = [UInt8](повтор: 0, количество: aesBlockSize) guard 0 == SecRandomCopyBytes(kSecRandomDefault, ivBytes.count и ivBytes) else { fatalError("Создание IV не удалось!") } делать { let aes = попробовать AES(key: Array(key.data(используя: .utf8)!), blockMode: CBC(iv: ivBytes)) let encrypted = попробовать aes.encrypt (Array (data)) ivBytes.append (contentOf: зашифрованный) outData = Data (байты: ivBytes) } ловить { print("Ошибка шифрования: \(ошибка)") } } еще { let ivBytes = Array(Array(data).dropLast(data.count - aesBlockSize)) let inBytes = Array(Array(data).dropFirst(aesBlockSize)) делать { let aes = попробовать AES(key: Array(key.data(используя: .utf8)!), blockMode: CBC(iv: ivBytes)) let decrypted = попробовать aes.decrypt (inBytes) outData = Data (байты: расшифрованы) } ловить { print("Ошибка расшифровки: \(ошибка)") } } вернуть 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
}
}
** Установка Pod Crypto Swift ** 1. Модуль 'CryptoSwift' #add для 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)
}
}
Обновление Swift 4.2
Здесь, например, мы зашифровываем строку в base64encoded string. И затем мы расшифровываем то же самое до читаемой строки. (Это будет так же, как наша входная строка).
В моем случае я использую это, чтобы зашифровать строку и вставить ее в QR-код. Затем другая сторона сканирует это и дешифрует то же самое. Таким образом, промежуточный не будет понимать QR-коды.
Шаг 1: зашифровать строку "Зашифровать мое сообщение 123"
Шаг 2: Зашифрованная base64Кодированная строка: +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
Надеюсь, это поможет.
Спасибо!!!
Вот библиотека, использующая новый API WebCrypto.
Не требуется соединительный заголовок, и он намного быстрее, чем CryptoSwift.
https://github.com/etienne-martin/WebCrypto.swift
Основанное на пароле шифрование
шифрование
let crypto = WebCrypto()
let input = Data("This is a string".utf8)
let password = "password123"
crypto.encrypt(data: input, password: password, callback: {(encrypted: Data?, error: Error?) in
print(encrypted!)
})
Дешифрирование
crypto.decrypt(data: encrypted, password: password, callback: {(decrypted: Data?, error: Error?) in
print(String(data: decrypted!, encoding: .utf8)!)
})
Ключ на основе шифрования
шифрование
let crypto = WebCrypto()
let input = Data("This is a string".utf8)
let key = "6f0f1c6f0e56afd327ff07b7b63a2d8ae91ab0a2f0c8cd6889c0fc1d624ac1b8"
let iv = "92c9d2c07a9f2e0a0d20710270047ea2"
crypto.encrypt(data: input, key: key, iv: iv, callback: {(encrypted: Data?, error: Error?) in
print(encrypted!)
})
Дешифрирование
crypto.decrypt(data: encrypted, key: key, iv: iv, callback: {(encrypted: Data?, error: Error?) in
print(String(data: decrypted!, encoding: .utf8)!)
})
Отказ от ответственности: я написал эту библиотеку.
Это довольно старый пост, но в XCode 10 добавлен модуль 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
}
Вы можете просто скопировать и вставить эти методы (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 байтов.
Попробуйте с кодом ниже, он работает для меня.
Шифрование 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;
}