在 python 和 swift 之间交换加密消息

2024-01-04

我需要一个 python 代码和一个 swift 代码交换加密消息。

这是我尝试过的:

  1. Fernet

在审查了这些选项之后,我认为对称密钥算法效果很好。

在 python 中(像往常一样),它是加密和解密简单 https://cryptography.io/en/latest/fernet/:

Fernet(key).encrypt(b"mdg") # encrypt
Fernet(key).decrypt(encryptedMsg) # decrypt

简而言之,它最初看起来很简单,大致如下:

func encrypt(key: String, msg: String) throws -> String {
  let data = Data(base64URL: key)!
  let symetricKey = try! SymmetricKey(data: d)
  let msgUtf8 = msg.data(using: .utf8)!
  let sealBox = try! AES.GCM.seal(msgUtf8, using: symetricKey, nonce: nil)
  return sealBox.combined.base64EncodedString();
}

然而,我一直无法在swift匹配python的Fernet中找到该算法。

  1. ChaCha

在寻找问题时,我发现了这个惊人的answer https://stackoverflow.com/questions/68601200/decrypt-fernet-encrypted-textpython-in-swift来自布拉姆。非常不幸的是,它只解决了我问题的一方面:在 python 中加密消息并在 swift 中解码它们。我还需要相反的过程。

怎么解决这个问题呢?


首先,我们首先需要一种方法来创建安全随机值来生成 IV 和密钥。您还可以使用 CryptoKit 生成密钥SymmetricKey并从中提取数据,但现在我将使用此函数。

extension Data {
    static func secureRandom(ofSize size: Int) -> Data {
        var output = [UInt8](repeating: 0, count: size)
        _ = SecRandomCopyBytes(kSecRandomDefault, size, &output)
        return Data(output)
    }
}

然后,我们需要计算 AES CBC 密文的可能性,这可以使用 CommonCrypto 来完成。

func encrypt(plaintext: Data, key: Data, iv: Data) -> Data {
    var encryptor: CCCryptorRef?
    defer {
        CCCryptorRelease(encryptor)
    }

    var key = Array(key)
    var iv = Array(iv)
    var plaintext = Array(plaintext)

    CCCryptorCreate(CCOperation(kCCEncrypt), CCAlgorithm(kCCAlgorithmAES), CCOperation(kCCOptionPKCS7Padding), &key, key.count, &iv, &encryptor)

    var outputBytes = [UInt8](repeating: 0, count: CCCryptorGetOutputLength(encryptor, plaintext.count, false))
    CCCryptorUpdate(encryptor, &plaintext, plaintext.count, &outputBytes, outputBytes.count, nil)

    var movedBytes = 0
    var finalBytes = [UInt8](repeating: 0, count: CCCryptorGetOutputLength(encryptor, 0, true))
    CCCryptorFinal(encryptor, &finalBytes, finalBytes.count, &movedBytes)

    return Data(outputBytes + finalBytes[0 ..< movedBytes])
}

以及具有 SHA-256 哈希函数的 HMAC。我建议在这里使用 CryptoKit 的 HMAC 实现,但为了简单起见,我使用了 CommonCrypto 实现。

func computeHMAC(_ data: Data, using key: Data) -> Data {
    var data = Array(data)
    var key = Array(key)
    var macOut = [UInt8](repeating: 0, count: Int(CC_SHA256_DIGEST_LENGTH))
    CCHmac(CCHmacAlgorithm(kCCHmacAlgSHA256), &key, key.count, &data, data.count, &macOut)
    return Data(macOut)
}

这将所有这些整合到以下内容中

let plaintext = Data("Hello world!".utf8)

let signingKey = Data.secureRandom(ofSize: kCCKeySizeAES128)
let cryptoKey = Data.secureRandom(ofSize: kCCKeySizeAES128)
let fernetKey = (signingKey + cryptoKey).base64EncodedString()

let version: [UInt8] = [0x80]
let timestamp: [UInt8] = {
    let timestamp = Int(Date().timeIntervalSince1970).bigEndian
    return withUnsafeBytes(of: timestamp, Array.init)
}()
let iv = Data.secureRandom(ofSize: kCCBlockSizeAES128)
let ciphertext = encrypt(plaintext: plaintext, key: cryptoKey, iv: iv)
let hmac = computeHMAC(version + timestamp + iv + ciphertext, using: signingKey)

let fernetToken = (version + timestamp + iv + ciphertext + hmac).base64EncodedString()

print("Fernet key: \(fernetKey)")
print("Fernet token: \(fernetToken)")

示例输出可以是

Fernet key: 7EwFlYNKTGfj+2fSgL3AUqtrRqRs4D1TWNK7t2XbGJQ=
Fernet token: gAAAAABivCLM0y0poDtGOohT1yK4XTDJppYPJdu4fuDTZ5tb9P9KP5ACgX8aJq4imsSdbzOCcvY3Tueo4FYbwyG+ZugozILL+Q==

我们可以使用 cryptography.io 的实现在 python 中使用它

from cryptography.fernet import Fernet

key = b'7EwFlYNKTGfj+2fSgL3AUqtrRqRs4D1TWNK7t2XbGJQ='
token = b'gAAAAABivCLM0y0poDtGOohT1yK4XTDJppYPJdu4fuDTZ5tb9P9KP5ACgX8aJq4imsSdbzOCcvY3Tueo4FYbwyG+ZugozILL+Q=='

Fernet(key).decrypt(token)
# b'Hello world!'
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 python 和 swift 之间交换加密消息 的相关文章

  • Kivy - 文本换行工作错误

    我正在尝试在 Kivy 1 8 0 应用程序中换行文本 当没有太多文字时 一切正常 但如果文本很长并且窗口不是很大 它只是剪切文本 这是示例代码 vbox BoxLayout orientation vertical size hint y
  • boto3 资源(例如 DynamoDB.Table)的类型注释

    The boto3库提供了几种返回资源的工厂方法 例如 dynamo boto3 resource dynamodb Table os environ DYNAMODB TABLE 我想注释这些资源 以便我可以获得更好的类型检查和完成 但我
  • for 循环如何评估其参数

    我的问题很简单 Does a for循环评估它每次使用的参数 Such as for i in range 300 python 是否会为此循环的每次迭代创建一个包含 300 个项目的列表 如果是的话 这是避免这种情况的方法吗 lst ra
  • 在 macOS 中通过 Python 访问进程的压缩 RAM(顶部的 CMPRS)的方法?

    我试图弄清楚如何从 Python 访问任何给定进程占用的实际 RAM 量 我发现 psutil Process PID memory info rss 工作得很好 直到操作系统决定开始压缩某些进程的 RAM 然后 所有的 memory in
  • 根据开始列和结束列扩展数据框(速度)

    我有一个pandas DataFrame含有start and end列 加上几个附加列 我想将此数据框扩展为一个时间序列 从start值并结束于end值 但复制我的其他专栏 到目前为止 我想出了以下内容 import pandas as
  • 更改 Altair 中的构面标题位置?

    如何将方面标题 在本例中为年份 移动到每个图的上方 默认值似乎位于图表的一侧 这可以轻易改变吗 import altair as alt from vega datasets import data df data seattle weat
  • 更改 python tkinter canvas 中的线坐标

    我画了一条线tkinter Canvas现在我想移动一端 这可能吗 例如和itemconfig import tkinter tk tkinter Tk canvas tkinter Canvas tk canvas pack line c
  • PySide6.1 与 matplotlib 3.4 不兼容

    当我只安装PySide6时 GUI程序运行良好 但是一旦我安装了matplotlib及其依赖包 包括pyqt5 则GUI程序将无法运行并输出以下错误消息 This application failed to start because no
  • Pandas 滚动窗口 Spearman 相关性

    我想使用滚动窗口计算 DataFrame 两列之间的 Spearman 和 或 Pearson 相关性 我努力了df corr df col1 rolling P corr df col2 P为窗口尺寸 但我似乎无法定义该方法 添加meth
  • 在Python中计算内存碎片

    我有一个长时间运行的进程 不断分配和释放对象 尽管正在释放对象 但 RSS 内存使用量会随着时间的推移而增加 如何计算发生了多少碎片 一种可能性是计算 RSS sum of allocations 并将其作为指标 即便如此 我该如何计算分母
  • Python多处理错误“ForkAwareLocal”对象没有属性“连接”

    下面是我的代码 我面临着多处理问题 我看到这个问题之前已经被问过 我已经尝试过这些解决方案 但它似乎不起作用 有人可以帮我吗 from multiprocessing import Pool Manager Class X def init
  • 自动生成的 Swift 桥接标头中“找不到接口声明”

    我当前的项目包含 Swift 和 Objective C 代码 两种类型的源文件都使用另一种语言的代码 当我进行完全清理并重新编译时 几乎每个 Swift 类声明都出现错误Module Swift h 形式为 Cannot find int
  • Pandas style.bar 颜色基于条件?

    如何渲染其中一列的 Pandas dfstyle bar color属性是根据某些条件计算的 Example df style bar subset before after color ff781c vmin 0 0 vmax 1 0 而
  • 解析根元素内元素之间的 XML 文本

    我正在尝试用 Python 解析 XML 以下是 XML 结构的示例 a aaaa1 b bbbb b aaaa2 a
  • 无法在 python 3.8 上将带有 webapp 的 python 部署到 azure

    我正在尝试使用部署一个测试项目Flask使用以下方法将框架迁移到 Azure 云中Azure CLI https learn microsoft com en us azure app service containers quicksta
  • 如何在 SwiftUI 中延迟动画?

    我想为两个文本字段设置动画 第二个字段有延迟 但它不起作用 没有延迟 它们同时从位置 100 动画到 0 这是代码 State private var offset CGFloat 100 State private var offset2
  • 如何使用 matplotlib 为圆柱体的每个单独面添加颜色

    我正在尝试为圆柱体的每个面着色 但是我不确定如何进行 我尝试了以下方法 for i in range 10 col append for i in range 10 for j in range 20 col i append plt cm
  • 为什么 smtplib.SMTP().sendmail 不发送 DKIM 签名邮件

    我已经在服务器上设置了 postfix 以及 openDKIM 当我跑步时 echo Testing setup mail s Postfix test my email address 我收到电子邮件 邮件标题中有一个DKIM Signa
  • Python:高精度time.sleep

    你能告诉我如何在 Win32 和 Linux 上的 Python 2 6 中获得高精度睡眠函数吗 您可以在中使用浮点数sleep http docs python org library time html time sleep 该参数可以
  • 缓存 Flask-登录 user_loader

    我有这个 login manager user loader def load user id None return User query get id 在我引入 Flask Principal 之前它运行得很好 identity loa

随机推荐