Reputation: 568
I am using AES256
algorithm CBC mode
with pkc7
padding. I have backend in Node.js
. But getting first 12 random characters.
Here is my swift code:
func encrypt(data: Data, key: Data, iv: Data) throws -> Data? {
// Output buffer (with padding)
let outputLength = data.count + kCCBlockSizeAES128
var outputBuffer = Array<UInt8>(repeating: 0,
count: outputLength)
//var outputBuffer: [UInt8] = []
var numBytesEncrypted = 0
let status = CCCrypt(CCOperation(kCCEncrypt),
CCAlgorithm(kCCAlgorithmAES),
CCOptions(kCCOptionPKCS7Padding),
Array(key),
kCCKeySizeAES256,
Array(iv),
Array(data),
data.count,
&outputBuffer,
outputLength,
&numBytesEncrypted)
guard status == kCCSuccess else { return nil }
let outputBytes = iv + outputBuffer.prefix(numBytesEncrypted)
return Data(bytes: outputBytes)
}
How can I do without padding? Or what should be done from backend?
Upvotes: 2
Views: 6574
Reputation: 874
You can use tags before and after payload you want to share. That tag will be your headers.
like <tag>string</tag>
So if you encrypt you will get first 12 random bytes
so you need to ignore text other than between **<tag>...</tag>**
Upvotes: 1
Reputation: 12988
There's nothing wrong with what you posted, you probably just got some parameter incorrect somewhere between Swift and node.js.
First of all it's a good idea to check that you can decrypt locally, in the same language, whatever you encrypted. Using information from the screenshot you posted (note for the future: also post everything in text, typing in base 64 encoded data from a screenshot far more tedious than copy and paste).
In your case, in Swift, that would look like this:
import UIKit
import CommonCrypto
var key = "zewQjVQMGdoEJK0yHtLcbP3ZlHOKjERG"
// This is the ciphertext with the initialization vector prepended.
let base64String = "w93bonVuqtW22Drj4HtZ3zNtNSt+5OBMapGGHekLCFA="
var data = Data(base64Encoded: base64String)!
// Split out the initialization vector and ciphertext
var iv = data[0..<kCCBlockSizeAES128]
var ciphertext = data[kCCBlockSizeAES128..<data.count]
var outputLength = data.count
var outputBuffer = Array<UInt8>(repeating:0, count: outputLength)
var bytesDecrypted = 0
let status = CCCrypt(CCOperation(kCCDecrypt),
CCAlgorithm(kCCAlgorithmAES),
CCOptions(kCCOptionPKCS7Padding),
Array(key.utf8),
kCCKeySizeAES256,
Array(iv),
Array(ciphertext),
ciphertext.count,
&outputBuffer,
outputLength,
&bytesDecrypted
)
print(String(bytes: outputBuffer.prefix(bytesDecrypted), encoding: .utf8))
// Optional("gmail.com")
Once you know that all is working well in the same language try it in the other. Now I don't know much about node.js, but going line-by-line through the Swift would lead to this:
const crypto = require('crypto')
let keyString = 'zewQjVQMGdoEJK0yHtLcbP3ZlHOKjERG'
let key = Buffer.from(keyString, 'utf8')
let base64String = 'w93bonVuqtW22Drj4HtZ3zNtNSt+5OBMapGGHekLCFA='
let ivPlusCiphertextBuffer = Buffer.from(base64String, 'base64')
// Split out the initialization vector and the ciphertext
let blockSize = 16 // Don't know how to get this in Node.js so hard-code it
let iv = ivPlusCiphertextBuffer.subarray(0, blockSize)
let ciphertext = ivPlusCiphertextBuffer.subarray(blockSize, ivPlusCiphertextBuffer.length)
let decryptor = crypto.createDecipheriv('aes-256-cbc', key, iv)
var plaintext = decryptor.update(ciphertext, 'binary', 'utf8')
plaintext += decryptor.final('utf8')
console.log(plaintext)
// gmail.com
So as long as you get the output of your Swift routines to the input of a node.js routine that looks something like my example above, you should be good to go!
Upvotes: 1