快速从模数和指数创建SecKey [英] Create SecKey from modulus and exponent in swift

查看:150
本文介绍了快速从模数和指数创建SecKey的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我尝试用

exponent:
let exponent = "10001"

modulus: 
let modulus = "D6250B831F82EC984513922E797283E4D3879E1F0AD52364EBDA5A5696F6E75CDCE0704A993F3F95AA557A6882A525EC4B8344DA3E7DFDECCBACCEF18131E461D3C5D3D7E1334C6AE27E5CDEF8A577857542BCBEF6CF021B0EE5604534E6C6CBAEFA6EFFC1AB93DEE7CE51A8C8F2B7345680BDF840841C3A6F654CD1F10BA2FD5CA1C6E782A8FAEC79BD22FA12116D75FFAEDB2DEC151E0B60DB91F2E74BA78EFBB45DF739AF9CDD41C482DC22FC76E03C8E2141BDAE5406C0DA230E2C7EFFC68C8811E1544496332B03BCFF0F627A8DF51D2E2B32B0771D1C6F87AD56010DCB7A3862C63B88B2CF7D7AD40CC53AF0CFEC0820777C9CCE95A58848D67779AE8D"

作为 publicKey 在 Swift 中加密文本.有人能帮我吗?

as publicKey to encrypt a text in Swift. Can someone help me?

这是我的代码:

import Foundation
import Security

class Encryption {

var publicKeyPtr, privateKeyPtr: Unmanaged<SecKey>?
var publicKey, privateKey: SecKey?
let parameters: [String:String] = [kSecAttrKeyType: kSecAttrKeyTypeRSA, kSecAttrKeySizeInBits: "2048"]

init(){

}

func genKey() {

    let status = SecKeyGeneratePair(parameters, &publicKeyPtr, &privateKeyPtr)
    publicKey = publicKeyPtr!.takeRetainedValue()
    privateKey = privateKeyPtr!.takeRetainedValue()

}


func encrypt(plainText: String, publicKey: SecKey) -> [UInt8]{
    let blockSize = SecKeyGetBlockSize(publicKey)
    let plainTextData = [UInt8](plainText.utf8)
    let plainTextDataLength = UInt(countElements( plainText))
    var encryptedData = [UInt8](count: Int(blockSize), repeatedValue: 0)
    var encryptedDataLength = blockSize
    let result = SecKeyEncrypt(publicKey, SecPadding(kSecPaddingPKCS1),
        plainTextData, plainTextDataLength, &encryptedData, &encryptedDataLength)

    return encryptedData
}


func decrypt(data: [UInt8]) -> String{
    let blockSize = SecKeyGetBlockSize(publicKey)
    var decryptedData = [UInt8](count: Int(blockSize), repeatedValue: 0)
    var decryptedDataLength = blockSize
    let result = SecKeyDecrypt(privateKey, SecPadding(kSecPaddingPKCS1),
        data, blockSize,
        &decryptedData, &decryptedDataLength)

    let decryptedText = String(bytes: decryptedData,
        encoding:NSUTF8StringEncoding)

    return decryptedText!
}

}

推荐答案

对于任何仍在寻找答案的人,也许我可以提供帮助.

For anyone still looking for an answer to this maybe I can help.

从 iOS 10 开始,您可以使用 SecKeyCreateWithData 从该密钥的外部表示创建一个 SecKey.

Since iOS 10 you can use SecKeyCreateWithData to create a SecKey from an external representation of that key.

此表示的格式应与 SecKeyCopyExternalRepresentation 返回的格式相同.如文档 中所述,RSA 密钥的格式为 PCKS#1.

The format of this representation should be the same as the one returned by SecKeyCopyExternalRepresentation. As discussed in the docs, that format is PCKS#1 for an RSA key.

因此,为了根据给定的模数和指数创建 SecKey,我们需要获得该密钥的 PKCS#1 表示.

So in order to create a SecKey from a given modulus and exponent, we need to obtain the PKCS#1 representation of that key.

引用自 PKCS#1:

RSA 公钥应该用 ASN.1 类型表示
RSA公共密钥:

An RSA public key should be represented with the ASN.1 type
RSAPublicKey:

  RSAPublicKey ::= SEQUENCE {
      modulus           INTEGER,  -- n
      publicExponent    INTEGER   -- e
  }

RSAPublicKey 类型的字段含义如下:

The fields of type RSAPublicKey have the following meanings:

  • 模数是 RSA 模数 n.
  • publicExponent 是 RSA 公共指数 e.

此 ASN.1 类型需要使用 DER 获取SecKeyCreateWithData 期望的数据.

This ASN.1 type needs to be expressed using DER to obtain the data that SecKeyCreateWithData expects.

下面我将尝试讨论如何在 Swift 中获取所需的数据格式.请注意,您可能也可以从命令行使用 OpenSSL 执行此操作,如果您只需要执行一次,这可能会更容易.

Below you I'll try to discuss how to get the desired data format in Swift. Please note that you can probably also do that using OpenSSL from the command line which might be easier if you just need to do it once.

这篇文章 作者 Ignacio Nieto Carvajal.

A good overview of what needs to be done is given in this article by Ignacio Nieto Carvajal.

基本上,您需要将模数和指数都编码为 DER INTEGER 然后将它们组合在 DER 序列.

Basically, you need to encode both the modulus and exponent as DER INTEGER and then combine them in a DER SEQUENCE.

您可以找到一些有关如何执行此操作的代码在这里这里.(免责声明:我是该库的贡献者之一.)

You can find some code on how to do that here and here. (Disclamer: I am one of the contributors of that library.)

我会在下面总结一下.

假设我们有一个 RSA 模数和公共指数作为字节数组.从模数和指数的不同表示中获取字节数组应该不会太难.

let exponent: [UInt8] = [
    1, 0, 1
]

var modulus: [UInt8] = [
    136, 0, 243, 196, 194, 126, 151, 243, 72, 84, 246, 234, 207, 215, 168, 5, 233, 212, 8, 37, 34, 52, 215, 217, 223, 183, 58, 129, 66, 112, 88, 71, 201, 71, 33, 156, 132, 7, 189, 234, 110, 6, 46, 189, 233, 206, 61, 128, 220, 138, 56, 49, 34, 159, 245, 208, 214, 49, 169, 58, 170, 68, 127, 93, 137, 99, 74, 54, 65, 109, 112, 33, 65, 169, 246, 176, 128, 121, 171, 35, 214, 236, 210, 123, 94, 146, 86, 30, 134, 135, 116, 124, 4, 55, 208, 163, 219, 220, 203, 249, 107, 69, 147, 169, 66, 214, 179, 195, 152, 211, 209, 78, 100, 114, 209, 203, 120, 16, 254, 24, 39, 143, 79, 49, 202, 10, 37, 2, 155, 162, 14, 253, 194, 205, 74, 116, 60, 205, 25, 53, 85, 144, 72, 11, 7, 133, 78, 149, 111, 0, 215, 174, 36, 104, 175, 62, 196, 197, 49, 78, 172, 146, 82, 216, 160, 45, 48, 212, 50, 168, 208, 255, 205, 82, 22, 11, 13, 156, 197, 42, 159, 26, 124, 237, 178, 131, 239, 186, 37, 96, 24, 154, 243, 202, 252, 87, 102, 23, 19, 29, 73, 130, 95, 45, 219, 104, 13, 54, 30, 165, 144, 223, 1, 14, 169, 100, 111, 246, 54, 185, 47, 156, 238, 249, 88, 33, 244, 135, 233, 102, 36, 86, 196, 143, 178, 176, 62, 24, 178, 209, 163, 244, 116, 236, 81, 177, 190, 205, 140, 230, 6, 113, 158, 105, 111, 123
]

然后我们需要确保模数以 0x00 为前缀到 表示它是一个非负数.

We then need to make sure that the modulus is prefixed with 0x00 to indicate that it is a non-negative number.

modulus.insert(0x00, at: 0)

现在我们将模数和指数编码为 整数.

var modulusEncoded: [UInt8] = []
modulusEncoded.append(0x02)
modulusEncoded.append(contentsOf: lengthField(of: modulus))
modulusEncoded.append(contentsOf: modulus)

var exponentEncoded: [UInt8] = []
exponentEncoded.append(0x02)
exponentEncoded.append(contentsOf: lengthField(of: exponent))
exponentEncoded.append(contentsOf: exponent)

并结合这些 INTEGERs序列.

var sequenceEncoded: [UInt8] = []
sequenceEncoded.append(0x30)
sequenceEncoded.append(contentsOf: lengthField(of: (modulusEncoded + exponentEncoded)))
sequenceEncoded.append(contentsOf: (modulusEncoded + exponentEncoded))

以下是用于计算上面使用的 DER 类型的长度字段的辅助函数:

func lengthField(of valueField: [UInt8]) -> [UInt8] {
    var count = valueField.count

    if count < 128 {
        return [ UInt8(count) ]
    }

    // The number of bytes needed to encode count.
    let lengthBytesCount = Int((log2(Double(count)) / 8) + 1)

    // The first byte in the length field encoding the number of remaining bytes.
    let firstLengthFieldByte = UInt8(128 + lengthBytesCount)

    var lengthField: [UInt8] = []
    for _ in 0..<lengthBytesCount {
        // Take the last 8 bits of count.
        let lengthByte = UInt8(count & 0xff)
        // Add them to the length field.
        lengthField.insert(lengthByte, at: 0)
        // Delete the last 8 bits of count.
        count = count >> 8
    }

    // Include the first byte.
    lengthField.insert(firstLengthFieldByte, at: 0)

    return lengthField
}

现在我们终于有了我们想要的数据.

let keyData = Data(bytes: sequenceEncoded)

您可以使用此数据创建SecKey.

// RSA key size is the number of bits of the modulus.
let keySize = (modulus.count * 8)

let attributes: [String: Any] = [
    kSecAttrKeyType as String: kSecAttrKeyTypeRSA,
    kSecAttrKeyClass as String: kSecAttrKeyClassPublic,
    kSecAttrKeySizeInBits as String: keySize
]

let publicKey = SecKeyCreateWithData(keyData as CFData, attributes as CFDictionary, nil)

我希望这会有所帮助!如果您需要更多信息,请告诉我.

I hope this helps! Let me know if you need any more info.

这篇关于快速从模数和指数创建SecKey的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆