[iOS] Secure Coding

RudinP·2025년 6월 7일
0

Study

목록 보기
275/292

NSSecureCoding

구현

객체 클래스

  • NSSecureCoding 프로토콜 추가
  • decode 대신에 decodeObject(of, forKey) -> NSCoding 사용
    • of에는 구조체 타입을 전달할 수 없음. 반드시 클래스로 구현된 타입 전달.(String(x) NSString(O))
  • SecureCoding 사용 시 반드시 클래스를 사용해야 함
class Language: NSObject, NSCoding, NSSecureCoding {
	//필수
    static var supportsSecureCoding: Bool {
    	return true
    }
    
	let name: String
    let version: Double
    let logo: UIImage
    
    //필수 메소드
    //구조체가 아닌 클래스 사용 필수 -> 컴파일타입캐스트 사용
    func encode(with coder: NSCoder) {
    	coder.encode(name as NSString, forKey: "name") //박싱, Boxing
        coder.encode(version as NSNumber, forKey: "version")
        coder.encode(logo, forKey: "logo")
    }
    //필수 메소드
    required init?(coder: NSCoder) {
    	guard let nameValue = coder.decodeObject(of: NSString.self, forKey: "name") as? String else { return nil }
        name = nameValue
        
        guard let versionValue = coder.decodeObject(of: NSNumber.self, forKey: "version") else {
        	return nil
        }
        version = versionValue.doubleValue //언박싱, Unboxing
        
        guard let img = coder.decodeObject(of: UIImage.self, forKey: "logo") as? UIImage else { return nil }
        logo = img
    }
    
    init(name: String, version: Double, logo: UIImage) {
    	self.name= name
        self.version = version
        self.logo = logo
    }
}

encode

  • encode에서 NSKeyedArchiver.archivedData 사용 시 requiringSecureCoding의 값을 true로 전달
class ViewController: UIViewController {
	...
    func encodeObject() {
    	do {
        	guard let img = UIImage(named: "swift") else { return }
        	
            let obj = Language(name: "Swift", version: 5.9, logo: img)
            //여기
            let data = try NSKeyedArchiver.archivedData(withRootObject:obj, requiringSecureCoding: true)
            
            try data.write(to: fileUrl, options: .atomic)
        } catch {
        	print(error)
        }
    }
...
}

decode

  • 기존의 NSCoding에서는 decode 시 NSKeyedUnarchiver.unarchiveObject 에서 타입을 지정하지 않는다. 디코딩이 완료된 객체를 타입캐스팅 하는데 이 시점에서 취약점 공격 발생 가능
  • SecureCoding에서는 디코딩 시점에 타입을 명확히 지정
    • 따라서 코드에서 에러가 발생하거나 취약점 공격을 당할 확률이 낮아짐
class ViewController: UIViewController {
	...
    func decodeObject() {
    	do {
        	let data = try Data(contentsOf: fileUrl)
            //여기
            if let language = try NSKeyedUnarchiver.unarchivedObject(ofClass: Language.self, from: data) {
            	logoImageView.image = language.logo
                nameLabel.text = language.name
                versionLable.text = "\(language.version)"
            }
        } catch {
        	print(error)
        }
    }
}
profile
iOS 개발자가 되기 위한 스터디룸...

0개의 댓글