Download XCode projectRSA加密文件或文本
我加密消息,並將其保存到文件中。如果我在加密文件的同時解密文件,解密成功但是如果其他時間解密函數返回零。
我使用這個類來加密和解密。
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)
}
}
,如果我在這個時候解密是成功的解密文件。但是當我關閉程序並打開它並解密文件時,解密方法失敗了。
if let fileURL = dir?.appendingPathComponent(fileName).appendingPathExtension("dgk") {
var encryptDataFromFile: Data?
do {
encryptDataFromFile = try Data(contentsOf: fileURL)
if let decryptData: Data = self.crypt.decryptWithRSAKey(encryptDataFromFile!){
let decryptString: String = String(data: decryptData, encoding: .utf8)!
print(decryptString)
}
exit(0)
} catch {
print("Failed reading from URL: \(fileURL), Error: " + error.localizedDescription)
}
}
什麼是文件大小以字節爲單位?請注意,RSA可以加密的數據大小小於密鑰大小。即使對於原始RSA,1024位密鑰也被限制爲小於128字節。通常,不對稱加密(如RSA)不用於加密數據,數據通常使用對稱加密(如AES)進行加密。 – zaph
嘗試使用調試器隔離核心問題,並提供MWE。你已經分享了很多代碼來閱讀和記住。另外,什麼zaph說:你在做什麼是非常不規範的。這就是說,我注意到的一件事是:你爲什麼要自己去除填充物? – Raphael
@zaph大小爲768字節。我對尺寸要小心,而對於填充,我是負11,並且使用塊限制。我的問題是:第一次當我保存加密郵件工作時,但當我註釋保存到文件部分,並從文件中讀取並解密時,解密不起作用。因爲從RSA加密的服務器數據,我必須使用它。 –