微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

CryptoSwift-在iOS中将makeEncryptor用于少于16个字节的字符串时得到零

如何解决CryptoSwift-在iOS中将makeEncryptor用于少于16个字节的字符串时得到零

我正在使用cryptoSwift库进行加密和解密。但是它仅使用16个字节的字符串。如果我传递的是小字符串或少于16个字节,则结果为nil。

我正在使用Cryptor实例进行增量操作,并且一次加密/解密一个部分。

在这里帮助我,我做错了什么吗?

谢谢。

loc_perc = 0.5

dfNew = df.assign(
    temp=lambda x: x.Space,Reduced_Space=lambda x: np.where(x.Location == "Y",np.where((x.Space * dual_loc_perc) < x.Min,x.Space and x.Dual_Location ='',x.Space * dual_loc_perc),x.Space),).drop("temp",1)

解决方法

在CryptoSwift中实现aes-256-gcm并没有错,正如一些评论者所建议的那样,您的代码中仅包含一些错误。希望以下内容能对您有所帮助。

为简便起见,我在下面将其称为GCM。

GCM加密将纯文本,密钥和初始化向量作为输入,并生成密文和身份验证标签。在您的代码中,将身份验证标签设置为随机字节,从而覆盖身份验证标签。

我认为,如果将代码分解为一些功能,每个功能都有明确的定义,这会更清楚一些。为了清楚起见,我还剥离了从Data[UInt8]的一些转换。

这是加密功能的样子:

func enc(plainText: [String],key: [UInt8],iv: [UInt8]) throws -> (cipherText: [UInt8],authenticationTag: [UInt8]?)
{
    let gcmEnc = GCM(iv: iv,mode: .detached)
    var enc = try AES(key: key,blockMode: gcmEnc,padding: .noPadding).makeEncryptor()
    var ciphertext = Array<UInt8>()
    for txt in plainText {
         ciphertext  += try enc.update(withBytes: Array(txt.utf8))
    }
    ciphertext += try enc.finish()
    return (ciphertext,gcmEnc.authenticationTag)
}

解密GCM时,您需要输入密文,密钥,初始化向量身份验证标签。看起来像这样:

func dec(cipherText: [UInt8],authenticationTag: [UInt8]?,iv: [UInt8]) throws -> [UInt8]? {
    let tagLength = authenticationTag?.count ?? 0
    let gcmDec = GCM.init(iv: iv,additionalAuthenticatedData: nil,tagLength: tagLength,mode: .detached)
    gcmDec.authenticationTag = authenticationTag
    var aesDec = try AES(key: key,blockMode: gcmDec,padding: .noPadding).makeDecryptor()
    var decData = try aesDec.update(withBytes: cipherText)
    decData += try aesDec.finish()
    return decData
}

在两种情况下,都需要确保将finish调用的输出附加到密文或纯文本中。这对于少量数据尤为重要,因为update方法可能不会产生任何结果!

编写了这两个函数后,您可以按以下方式重写测试函数:

func encAndDec(){
    do {
        guard let key =  Data.init(base64Encoded: "12345678901234567890123456789012".base64Encoded()!)
            else {
                fatalError("Failed to create key")
        }
        let iv : Array<UInt8> = [0,0]

        //let arrStr = ["My name is tarun"] // Working
        let arrStr = ["tarun"] // Not working for this string
        
        let (cipherText,authenticationTag) = try enc(plainText: arrStr,key: key.bytes,iv: iv)
        guard let decrypedPlainText = try dec(cipherText: cipherText,authenticationTag: authenticationTag,iv: iv) else {
            fatalError("Decryption return nil")
        }
        guard let decryptedString = String(bytes: decrypedPlainText,encoding: .utf8) else {
            fatalError("Failed to convert plaintext to string using UTF8 encoding.")
        }

        print("Decrypted Plaintext: \(decryptedString)")

    }
    catch let e {
        print("EXCEPTION: \(e)")
    }
}

如果运行此命令,则会发现它会产生预期的输出。

完整的示例代码可在以下位置找到:https://gist.github.com/iosdevzone/45456d2911bf2422bc4a6898876ba0ab

,

我不认为GCM需要填充。这是直接来自NODE.JS文档的示例,可以很好地工作并且不使用填充。下面的行将显示密文长度为5

我对Ruby,Java,Go和其他代码也做了同样的事情,没有一个需要填充或输入值是16字节的倍数,就像Swift库似乎需要的那样。其他人可以帮助确认这是GCM的Swift实施中的错误吗?

const crypto = require('crypto');

const key = '12345678901234567890123456789012';
const iv = '000000000000'

const cipher = crypto.createCipheriv('aes-256-gcm',key,iv);  
const plaintext = 'Hello';  
const ciphertext = cipher.update(plaintext,'utf8');  
**console.log("ciphertext length %d",ciphertext.length)**  

cipher.final();  
const tag = cipher.getAuthTag();

const decipher = crypto.createDecipheriv('aes-256-gcm',iv);  
decipher.setAuthTag(tag);  
const receivedPlaintext = decipher.update(ciphertext,null,'utf8');  

try {
  decipher.final();
} catch (err) {
  console.error('Authentication failed!');
  return;
}

console.log(receivedPlaintext);

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。