swift - 来自公钥字符串的 Swift 4 中的 RSA 加密函数

标签 swift encryption jwt rsa jwe

我的最终目标是创建一个 JWE 字符串,给定一个 iOS 公钥。

为了让我自己更轻松,我已经分解了最紧迫的步骤,我需要使用来自 secret key 和公钥字符串的 RSA 加密来创建加密 key 。

我已经尝试了很多在 stack overflow 和互联网其他地方找到的东西。由于各种原因,他们只是没有成功。

我正在接受一些 Objective C 代码的指导:

/* Device Data encryption - create JWE given DS publicKey */ +(NSString *)createJWE:(NSString *)payload withPublicKey:(SecKeyRef)publicKey {
// create secretKey for encryption
NSData *secret = [self generateRandom:(KEY_SIZE*2)];
NSData *hmacKey = [secret subdataWithRange:NSMakeRange(0, KEY_SIZE)]; NSData *aesKey = [secret subdataWithRange:NSMakeRange(KEY_SIZE,
KEY_SIZE)];
  NSData *iv = [self generateRandom: IV_SIZE];
// create header
NSString *header = @"{\"enc\":\"A128CBC-HS256\",\"alg\":\"RSA-OAEP\"}";
// encrypt secretKey
NSData *encryptedKey = [self rsaEncrypt:secret key:publicKey];
  // encrypt payload
NSData *encrypted = [self aesEncrypt:[payload dataUsingEncoding:NSUTF8StringEncoding] withKey:aesKey withIV:iv];
NSString *basePayload = [encrypted unpaddedBase64URLEncoded];
NSString *baseCEK = [encryptedKey unpaddedBase64URLEncoded];
NSString *baseHeader = [[header dataUsingEncoding:NSUTF8StringEncoding]
unpaddedBase64URLEncoded];
NSString *baseIV = [iv unpaddedBase64URLEncoded];
// create auth hash
NSData *hmac = [self hmac: encrypted withKey: hmacKey withIV: iv withA:
[baseHeader dataUsingEncoding:NSASCIIStringEncoding]];
return [NSString stringWithFormat:@"%@.%@.%@.%@.%@", baseHeader, baseCEK, baseIV, basePayload, [[self hmacToTag: hmac] unpadded

我目前正处于函数的这一点:

NSData *encryptedKey = [self rsaEncrypt:secret key:publicKey];

由此我假设存在一个接受 secret 和公钥的 rsaEncrypt 函数。

我有权访问的公钥如下所示:

let publicKey = """
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDEChqe80lJLTTkJD3X3Lyd7Fj+
zuOhDZkjuLNPog3YR20e5JcrdqI9IFzNbACY/GQVhbnbvBqYgyql8DfPCGXpn0+X
NSxELIUw9Vh32QuhGNr3/TBpechrVeVpFPLwyaYNEk1CawgHCeQqf5uaqiaoBDOT
qeox88Lc1ld7MsfggQIDAQAB
-----END PUBLIC KEY-----
"""

在 Internet 上找到的示例将公钥处理为 SecKey 类型。这是我执行加密的第一个障碍。

  1. 如果必须转换字符串,如何将其转换为 SecKey?
  2. 我的 rsaEncrypt 函数应该做什么?

我希望在执行加密后输出为加密 key 。

更新:另一种变体,发送的一个公钥也如下所示:

{ "kty": "RSA", "kid": "UUIDkeyidentifierforDS", "use": "enc", "n": "n4EPtAOCc9AlkeQHPzHStgAbgs7bTZLwUBZdR8_KuKPEHLd4rHVTeT-O- XV2jRojdNhxJWTDvNd7nqQ0VEiZQHz_AJmSCpMaJMRBSFKrKb2wqVwGU_NsYOYL- QtiWN2lbzcEe6XC0dApr5ydQLrHqkHHig3RBordaZ6Aj-oBHqFEHYpPe7Tpe- OfVfHd1E6cS6M1FZcD1NNLYD5lFHpPI9bTwJlsde3uhGqC0ZCuEHg8lhzwOHrtIQbS0F Vbb9k3- tVTU4fg_3L_vniUFAKwuCLqKnS2BYwdq_mzSnbLY7h_qixoR7jig3__kRhuaxwUkRz5i aiQkqgc5gHdrNP5zw", "e": "AQAB" }

最佳答案

你可以这样做......

static func encrypt(string: String, publicKey: String?) -> String? {
        guard let publicKey = publicKey else { return nil }

        let keyString = publicKey.replacingOccurrences(of: "-----BEGIN PUBLIC KEY-----\n", with: "").replacingOccurrences(of: "\n-----END PUBLIC KEY-----", with: "")
        guard let data = Data(base64Encoded: keyString) else { return nil }

        var attributes: CFDictionary {
            return [kSecAttrKeyType         : kSecAttrKeyTypeRSA,
                    kSecAttrKeyClass        : kSecAttrKeyClassPublic,
                    kSecAttrKeySizeInBits   : 2048,
                    kSecReturnPersistentRef : kCFBooleanTrue] as CFDictionary
        }

        var error: Unmanaged<CFError>? = nil
        guard let secKey = SecKeyCreateWithData(data as CFData, attributes, &error) else {
            print(error.debugDescription)
            return nil
        }
        return encrypt(string: string, publicKey: secKey)
    }

    static func encrypt(string: String, publicKey: SecKey) -> String? {
        let buffer = [UInt8](string.utf8)

        var keySize   = SecKeyGetBlockSize(publicKey)
        var keyBuffer = [UInt8](repeating: 0, count: keySize)

        // Encrypto  should less than key length
        guard SecKeyEncrypt(publicKey, SecPadding.PKCS1, buffer, buffer.count, &keyBuffer, &keySize) == errSecSuccess else { return nil }
        return Data(bytes: keyBuffer, count: keySize).base64EncodedString()
    }

关于swift - 来自公钥字符串的 Swift 4 中的 RSA 加密函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56806553/

相关文章:

java - 将经过身份验证的用户保存到来自 Azure AD 的数据库

ios - 以编程方式将目标添加到按钮会引发错误 "unrecognized selector sent to class"

Spring 安全 : How to use a UserDetailsService with JwtAuthenticationProvider?

node.js - 将 Passport openID 策略与 JWT 相结合

c++ - 将 C++ builder 6 项目转换为 C++ builder 2010

ruby-on-rails - 更改设计和 rails 3 以使用 bcrypt 而不是 sha

java - 使用 PHP 和 Java 以流形式解密/加密文件 - 填充?

ios - 我怎样才能在 Swift 5.1 (Xcode 11 Playground) 中为可选项实现泛型和非泛型函数签名的重载?

ios - 将内容从 Firebase 拉入 Swift 的问题

swift - Alamofire:创建字典数组