본문 바로가기

ios

rsa256, rs256

공개키 구조

n값과 e값으로 구성되어있다.

n값은 Modulus이며 e값은 Public exponent값입니다.

 

Modulus

모듈러스는 공개키에서 중요한 역할을 하며, 두 큰 소수인 p와 q의 값으로 계산된다.

이 값은 RSA 알고리즘의 핵심인 모듈러 연산에서 사용된다.

구체적으로 모듈러스는 공개키와 개인키의 연산에 사용되며, RSA 암호화 및 복호화에서 중요한 역할을 한다.

p와 q는 매우 큰 소수들이다. 
이 값은 공개키와 객인키 모두에서 사용되며, 키의 길이는 이 값의 크기에 따라 결정된다.
RSA 키의 보안은 이 묘듈러 연산의 특성에 의존하며, 큰 소수의 곱을 소인수 분해하는 것은 매우 어려운 문제이다.

 

Exponent(공개키 지수)

공개키 지수는 보통 e로 표시되며, 이 값은 공개키의 일부로 다른 사람에게 알려진다.
공개 키 지수는 암호화 연사에서 메세지를 암호화 하는데 사용된다.


위의 xml 데이터(링크에서 확인하라는데 링크 속 주소가 없어짐, 이건 뭘까?)는 모두 문자열을 담고 있다.
바이너리(2진수)인 이 데이터를 담기 위해서는 인코딩이 필요합니다.
여기서 사용되는 인코딩이 Base64 인코딩입니다.

 

 

 

Rsa256 알고리즘으로 id token 서명을 검증하는 방법

RSA256은 RSA 알고리즘을 사용하여 SHA-256 해시 함수를 적용한 서명 알고리즘이다.

 

서명 검증 과정

1. JWT 구조 파싱

header.payload.signature

 

header : JWT 헤더에는 사용된 알고리즘이 명시된다.

payload : 실제 데이터(주로 클레임)가 포함된다.

signature : 헤더와 페이로드가 서명된 값이다.

 

2.헤더에서 알고리즘 추출

JWT의  헤더 부분에서 사용된 서명 알고리즘을 확인한다.

이 알고리즘이 RSA256인지 확인해야함.

 

3.서명 검증

  • 먼저 헤더와 페이로드는 base64로 인코딩된 문자열이다. 이를 디코딩하여 원본데이터를 얻는다.
  • 디코딩한 헤더와 페이로드를 Base64 URL-safe 형식으로 다시 인코딩해서 결합한다. 이때 헤더와 페이로드는 .으로 구분되어있다.
    • "\(encodedHeader).\(encodedPayload)"
  • 서명 부분을 base64 디코딩하여, 실제 서명을 얻는다.
  • RSA 공개키로 서명 검증은 진행한다. 공개키로 서명된 데이터의 해시 값과 디코딩된 서명 값이 일치하는 지 확인한다.
    • 공개 키로 데이터를 서명하는 방법과 그 데이터의 해시값을 얻는 방법
import Foundation
import Security

func verifyRSASignature(jwt: String, publicKey: SecKey) -> Bool {
    let segments = jwt.split(separator: ".")
    
    guard segments.count == 3 else {
        return false
    }
    
    let headerPayload = "\(segments[0]).\(segments[1])"
    
    // Base64url decode signature
    guard let signatureData = base64urlDecode(String(segments[2])) else {
        return false
    }
    
    // Create SHA256 hash of the message
    guard let messageData = headerPayload.data(using: .utf8) else {
        return false
    }
    let hash = sha256(messageData)
    
    // Verify signature with RSA public key
    return verifySignature(signatureData, withHash: hash, publicKey: publicKey)
}

func base64urlDecode(_ string: String) -> Data? {
    let modifiedString = string.replacingOccurrences(of: "-", with: "+").replacingOccurrences(of: "_", with: "/")
    let paddingLength = (4 - modifiedString.count % 4) % 4
    let paddedString = modifiedString + String(repeating: "=", count: paddingLength)
    
    return Data(base64Encoded: paddedString)
}

func sha256(_ data: Data) -> Data {
    var hash = Data(count: Int(CC_SHA256_DIGEST_LENGTH))
    _ = hash.withUnsafeMutableBytes { hashBytes in
        data.withUnsafeBytes { messageBytes in
            CC_SHA256(messageBytes.baseAddress, CC_LONG(data.count), hashBytes.baseAddress)
        }
    }
    return hash
}

func verifySignature(_ signature: Data, withHash hash: Data, publicKey: SecKey) -> Bool {
    var error: Unmanaged<CFError>?
    let isValid = SecKeyVerifySignature(publicKey,
                                        .rsaSignatureMessagePKCS1v15SHA256,
                                        hash as CFData,
                                        signature as CFData,
                                        &error)
    return isValid
}

 

참조 블로그

https://byul91oh.tistory.com/272

 

[RSA] RSA MODULUS, EXPONENT

RSA키는 비대칭키로 개인키와 공개키로 되어있습니다. 여기서 공개키와 개인키는 위에서 보시는 것과 같이 구조가 되어 있습니다. 일반적으로 공개키는 n값과 e 값으로 구성되어 있습니다. n값은

byul91oh.tistory.com

https://stackoverflow.com/questions/65361511/swift-load-rsa-public-key-from-string-macos