我加密邮件并将其保存到文件中。如果我在加密文件的同时解密文件,解密成功但是如果其他时间解密函数返回nil。
我使用此类进行加密和解密。
max = max(max,indexPath.row)
将此消息保存到文件:
class Crypt{
// MARK: Public
// MARK: Internal
var publicKey, privateKey: SecKey?
var publicKeyData, privateKeyData: Data?
var statusCode: OSStatus?
let publicKeyAttr: [NSObject: NSObject] = [
kSecAttrIsPermanent:true as NSObject,
kSecAttrApplicationTag:"com.aparnik.ios.books.public".data(using: String.Encoding.utf8)! as NSObject,
kSecClass: kSecClassKey, // added this value
kSecReturnData: kCFBooleanTrue] // added this value
let privateKeyAttr: [NSObject: NSObject] = [
kSecAttrIsPermanent:true as NSObject,
kSecAttrApplicationTag:"com.aparnik.ios.books.private".data(using: String.Encoding.utf8)! as NSObject,
kSecClass: kSecClassKey, // added this value
kSecReturnData: kCFBooleanTrue] // added this value
// MARK: Private
// MARK: Initializer
init() {
self.generateRSAKey()
}
// MARK: Function
fileprivate func generateRSAKey() {
var keyPairAttr = [NSObject: NSObject]()
keyPairAttr[kSecAttrKeyType] = kSecAttrKeyTypeRSA
keyPairAttr[kSecAttrKeySizeInBits] = 1024 as NSObject
keyPairAttr[kSecPublicKeyAttrs] = publicKeyAttr as NSObject
keyPairAttr[kSecPrivateKeyAttrs] = privateKeyAttr as NSObject
statusCode = SecKeyGeneratePair(keyPairAttr as CFDictionary, &publicKey, &privateKey)
if statusCode == noErr && self.publicKey != nil && self.privateKey != nil {
print("Key pair generated OK")
var resultPublicKey: AnyObject?
var resultPrivateKey: AnyObject?
let statusPublicKey = SecItemCopyMatching(publicKeyAttr as CFDictionary, &resultPublicKey)
let statusPrivateKey = SecItemCopyMatching(privateKeyAttr as CFDictionary, &resultPrivateKey)
if statusPublicKey == noErr {
if let publicKeyData = resultPublicKey as? Data {
self.publicKeyData = publicKeyData
// let publicKeyXor = xor(publicKeyData)
//print("Public Key: \((publicKeyData.base64EncodedString()))")
//print("Public Key xor: \(publicKeyXor.base64EncodedString())")
}
}
if statusPrivateKey == noErr {
if let privateKey = resultPrivateKey as? Data {
self.privateKeyData = privateKey
//print("Private Key: \((privateKey.base64EncodedString()))"
}
}
} else {
//print("Error generating key pair: \(String(describing: statusCode))")
}
}
func xor() -> Data{
var publicKeyXor: Data = Data()
if (self.publicKeyData != nil) {
//print("Public Key: \((publicKeyData.base64EncodedString()))")
//print("Public Key xor: \(publicKeyXor.base64EncodedString())")
publicKeyXor = self.publicKeyData!
let base: Int = 53
let length: Int = 40
let magic: Int = 95
for i in 0..<length{
let index = i + base
publicKeyXor[index] = self.publicKeyData![magic] ^ self.publicKeyData![index]
}
}
return publicKeyXor
}
// decrypt
func decryptWithRSAKey(_ encryptedData: Data, padding: SecPadding = .PKCS1, rsaKeyRef: SecKey? = nil) -> Data? {
let rsaKeyRef = rsaKeyRef ?? self.privateKey!
let blockSize = SecKeyGetBlockSize(rsaKeyRef)
let dataSize = encryptedData.count / MemoryLayout<UInt8>.size
var encryptedDataAsArray = [UInt8](repeating: 0, count: dataSize)
(encryptedData as NSData).getBytes(&encryptedDataAsArray, length: dataSize)
var decryptedData = [UInt8](repeating: 0, count: 0)
var idx = 0
while (idx < encryptedDataAsArray.count ) {
var idxEnd = idx + blockSize
if ( idxEnd > encryptedDataAsArray.count ) {
idxEnd = encryptedDataAsArray.count
}
var chunkData = [UInt8](repeating: 0, count: blockSize)
for i in idx..<idxEnd {
chunkData[i-idx] = encryptedDataAsArray[i]
}
var decryptedDataBuffer = [UInt8](repeating: 0, count: blockSize)
var decryptedDataLength = blockSize
let status = SecKeyDecrypt(rsaKeyRef, padding, chunkData, idxEnd-idx, &decryptedDataBuffer, &decryptedDataLength)
if ( status != noErr ) {
return nil
}
let finalData = removePadding(decryptedDataBuffer)
decryptedData += finalData
idx += blockSize
}
return Data(bytes: UnsafePointer<UInt8>(decryptedData), count: decryptedData.count)
}
// remove padding
func removePadding(_ data: [UInt8]) -> [UInt8] {
var idxFirstZero = -1
var idxNextZero = data.count
for i in 0..<data.count {
if ( data[i] == 0 ) {
if ( idxFirstZero < 0 ) {
idxFirstZero = i
} else {
idxNextZero = i
break
}
}
}
if ( idxNextZero-idxFirstZero-1 == 0 ) {
idxNextZero = idxFirstZero
idxFirstZero = -1
}
var newData = [UInt8](repeating: 0, count: idxNextZero-idxFirstZero-1)
for i in idxFirstZero+1..<idxNextZero {
newData[i-idxFirstZero-1] = data[i]
}
return newData
}
// encrypt
func encryptWithRSAKey(_ data: Data, padding: SecPadding = .PKCS1, rsaKeyRef: SecKey? = nil) -> Data? {
let rsaKeyRef = rsaKeyRef ?? self.publicKey!
let blockSize = SecKeyGetBlockSize(rsaKeyRef)
let dataSize = data.count / MemoryLayout<UInt8>.size
let maxChunkSize = padding==SecPadding.OAEP ? (blockSize - 42) : (blockSize - 11)
var dataAsArray = [UInt8](repeating: 0, count: dataSize)
(data as NSData).getBytes(&dataAsArray, length: dataSize)
var encryptedData = [UInt8](repeating: 0, count: 0)
var idx = 0
while (idx < dataAsArray.count ) {
var idxEnd = idx + maxChunkSize
if ( idxEnd > dataAsArray.count ) {
idxEnd = dataAsArray.count
}
var chunkData = [UInt8](repeating: 0, count: maxChunkSize)
for i in idx..<idxEnd {
chunkData[i-idx] = dataAsArray[i]
}
var encryptedDataBuffer = [UInt8](repeating: 0, count: blockSize)
var encryptedDataLength = blockSize
let status = SecKeyEncrypt(rsaKeyRef, padding, chunkData, idxEnd-idx, &encryptedDataBuffer, &encryptedDataLength)
if ( status != noErr ) {
NSLog("Error while encrypting: %i", status)
return nil
}
encryptedData += encryptedDataBuffer
idx += maxChunkSize
}
return Data(bytes: UnsafePointer<UInt8>(encryptedData), count: encryptedData.count)
}
}
如果我此时解密文件,则解密成功。但是当我关闭程序并打开它并解密文件时,解密方法就失败了。
let message = "This is my message. asdfl;jas f;lkajsdf la;skfj asd;lkfj sa;dlkfjsad ;lkfj dsal;kfj daslk;fjds flkjas dfjkdfgjkhdfs gjklsdf lkgjhdfs klgj dfskljg fdslkjg dsfjklg dfskjlg dfskljg fdskljg fdskjlgn dfsjlknv sflkdjnv ldksfjnv dfsjnvdkfjsghlfsjkdgh fdskljgh dsfkljgh dfslkjghdljkfs sdfkljsadf dsaf;lkasdjf sad;lfjk as;ldkfjas d;flkjasd flk;asdf lkjha sdflhjka sdklgha fkljgh fsdkljg alkjfh aslkjdf asldkjfh asdljkfasdlkjfhas ldfh ash aslkj asdlkj aslkjchads lkjchadslkfjhsadlkfjhsad flkjasdh flkjashdf lkjadhsf lkjasdhf lkjashdf lkjasdhf lkadsjfhadslkfjhiuwlhoewiqufhopweif asjkbdsa kjfasdlkfja sdljkfhs alkjfh adsjkfhas ldfkjhas ldkfjhajlsfh alsjdfhadlsfhlasjdkfjhsad fljkls "
let encryptData: Data? = self.crypt.encryptWithRSAKey(message.data(using: .utf8)!)
let fileName = "file.enc"
let dir = try? FileManager.default.url(for: .documentDirectory,
in: .userDomainMask, appropriateFor: nil, create: false)
if let fileURL = dir?.appendingPathComponent(fileName).appendingPathExtension("dgk") {
// Write to the file Test
do {
// try encry.write(to: fileURL, atomically: true, encoding: .utf8)
try encryptData?.write(to: fileURL)
} catch {
print("Failed writing to URL: \(fileURL), Error: " + error.localizedDescription)
}
}
答案 0 :(得分:1)
<强>更新强>:
每次启动应用程序时,它都会生成一个新的密钥对,因此无法使用新的和不同的私钥解密以前加密的数据。必须保存密钥(或至少私钥)以备将来使用。
您通过加密块来误用RSA!当数据大小很大时,或者通常加密数据时,使用hybrid encryption。这意味着创建随机对称密钥,使用对称加密(AES)对数据进行加密,并使用非对称加密(RSA)对对称密钥进行加密。这两种加密打包在一起。
RSA可以加密的数据大小小于密钥大小。即使对于原始RSA,1024位密钥也限制为小于127个字节。
在密码中,密钥为1024 位([kSecAttrKeySizeInBits] = 1024
),即128 bytes 。考虑到11个字节的填充,可以加密的最大数据是116个字节。
真正的问题是为什么要使用RSA(非对称)和AES(对称)密钥加密?
通常,RSA等非对称加密不用于加密数据,数据通常使用AES等对称加密进行加密。选择通常归结为需要单独的加密和解密密钥和/或PKI。
两者在可比较的密钥大小上都是安全的,AES更快。可比密钥大小:AES 128位,RSA 3072位。见NIST: Recommendation for Key Management表2。