ios - 快速从模数和指数创建 SecKey

标签 ios security swift seckeyref

我尝试用

制作我自己的 SecKey
exponent:
let exponent = "10001"

modulus: 
let modulus = "D6250B831F82EC984513922E797283E4D3879E1F0AD52364EBDA5A5696F6E75CDCE0704A993F3F95AA557A6882A525EC4B8344DA3E7DFDECCBACCEF18131E461D3C5D3D7E1334C6AE27E5CDEF8A577857542BCBEF6CF021B0EE5604534E6C6CBAEFA6EFFC1AB93DEE7CE51A8C8F2B7345680BDF840841C3A6F654CD1F10BA2FD5CA1C6E782A8FAEC79BD22FA12116D75FFAEDB2DEC151E0B60DB91F2E74BA78EFBB45DF739AF9CDD41C482DC22FC76E03C8E2141BDAE5406C0DA230E2C7EFFC68C8811E1544496332B03BCFF0F627A8DF51D2E2B32B0771D1C6F87AD56010DCB7A3862C63B88B2CF7D7AD40CC53AF0CFEC0820777C9CCE95A58848D67779AE8D"

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

这是我的代码:

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!
}

最佳答案

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

SecKeyCreateWithData

从 iOS 10 开始,您可以使用 SecKeyCreateWithData从该 key 的外部表示创建 SecKey

此表示的格式应与 SecKeyCopyExternalRepresentation 返回的格式相同.正如在 docs 中讨论的那样,该格式是 RSA key 的 PCKS#1。

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

引自PKCS#1 :

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

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

The fields of type RSAPublicKey have the following meanings:

  • modulus is the RSA modulus n.
  • publicExponent is the RSA public exponent e.

这个ASN.1类型需要用DER表示获取 SecKeyCreateWithData 期望的数据。

以正确的格式获取数据

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

this article 中对需要完成的工作进行了很好的概述。作者:Ignacio Nieto Carvajal。

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

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

我将尝试在下面对其进行总结。

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

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
]

然后我们需要确保模数的前缀是 0x00indicate that it is a non-negative number .

modulus.insert(0x00, at: 0)

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

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)

并结合这些 INTEGERsSEQUENCE .

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)

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

更多资源

关于ios - 快速从模数和指数创建 SecKey,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27132937/

相关文章:

asp.net - 将 UserId 公开给客户端是否安全?

jsp - 基本身份验证 : Is it possible to setRemoteUser like getRemoteUser()

mysql - 当我使用 $this->data 时,是否可以防止 MySQL 注入(inject)?

swift - Realm 对象上的索引是属性的复合索引或每个属性的不同索引

ios - 根据推送通知对应用程序启动采取行动

javascript - iOS Chrome 上的 HTML5 历史 API

ios - 如何使用ios, objective-c 获取与json中的对象具有相同引用号的所有值

ios9 - Xcode 7 - Swift - 键盘在模拟器中正确显示但在实际设备上不正确

ios - Swift 4 JSON 解码器

ios - swift 2 : Change navigation title on a view related to a Tab Bar Controller