Download XCode projectRSAの暗号化ファイルやテキスト
私はメッセージを暗号化してファイルに保存します。もし私がファイルを暗号化するときに同じ時刻にファイルを解読すると、解読は成功するが、それ以外の時に解読関数はnilを返す。
私はこのクラスを暗号化と復号化に使用します。
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を提供してください。読んで心に留めておくためにたくさんのコードを共有しています。また、ザフは言った:あなたがやっていることは、非常に非標準的です。それは、私が指摘していることの一つは、なぜパディングを自分で取り除くのですか? – Raphael
@zaphサイズは768バイトです。私はサイズに注意しているし、パディングのためにマイナス11であり、制限のためにチャンクを使用する。私の問題は:暗号化メッセージの作業を保存するとき初めてですが、ファイルセクションに保存してファイルから読み込んで解読するだけで、解読は機能しません。 サーバからのデータがRSAで暗号化されているため、それを使用する必要があるためです。 –