클라우드 타고 포트와 파도
article thumbnail

개요

HSM(Hardware Security Module)을 사용해 RSA 키를 만들고, 그 키로 메시지를 서명한 다음, 서명값을 검증하는 과정을 Go 언어로 직접 구현해봤습니다.

이번 테스트는 nCipher HSM 환경에서 진행했으며, pkcs11 인터페이스를 통해 아래와 같은 순서로 작업을 수행했습니다:

  1. HSM에서 RSA 키 생성
  2. Go 코드로 메시지 서명
  3. 공개키 추출
  4. 서명 검증

참고로 HSM은 보안 장비라서 개인키는 외부로 절대 빠져나오지 않고, 공개키만 추출할 수 있습니다.

 

RSA 키 생성 (HSM 내부)

/opt/nfast/bin/generatekey pkcs11
  • 키 label: test2
  • 보호방식: module (테스트 용도)
  • 알고리즘: RSA, 사이즈: 2048bit

생성 후 HSM 내부적으로 개인키와 공개키가 자동 생성됩니다.

개인키: HSM 내부에 존재, 외부 추출 불가
공개키: pkcs11을 통해 추출 가능 

 

Go로 서명 (sign.go) 

// 메시지 파일 읽기
msg, _ := ioutil.ReadFile("message.txt")

// label=test2 개인키 객체 찾기 (PRIVATE_KEY)
template := []*pkcs11.Attribute{
    pkcs11.NewAttribute(pkcs11.CKA_LABEL, "test2"),
    pkcs11.NewAttribute(pkcs11.CKA_CLASS, pkcs11.CKO_PRIVATE_KEY),
}

// SHA256 + RSA_PKCS 메커니즘으로 서명 초기화
p.SignInit(session, []*pkcs11.Mechanism{
    pkcs11.NewMechanism(pkcs11.CKM_SHA256_RSA_PKCS, nil),
}, privateKey)

// 서명 결과 저장
signature, _ := p.Sign(session, msg)
os.WriteFile("sig_from_go.bin", signature, 0644)

 

  • SignInit에서 SHA256 해시 + RSA 서명을 수행
  • 최종 서명 결과는 sig_from_go.bin으로 저장됨

 

공개키 추출 (export_pub.go) 

// label=test2 공개키 객체 찾기 (PUBLIC_KEY)
template := []*pkcs11.Attribute{
    pkcs11.NewAttribute(pkcs11.CKA_LABEL, "test2"),
    pkcs11.NewAttribute(pkcs11.CKA_CLASS, pkcs11.CKO_PUBLIC_KEY),
}

// modulus(N), exponent(E) 추출
pubAttrs := p.GetAttributeValue(session, publicKeyObj, []*pkcs11.Attribute{
    pkcs11.NewAttribute(pkcs11.CKA_MODULUS, nil),
    pkcs11.NewAttribute(pkcs11.CKA_PUBLIC_EXPONENT, nil),
})

// RSA 공개키 구조 생성 및 PEM 인코딩
rsa.PublicKey{
    N: new(big.Int).SetBytes(modulus),
    E: exponent,
}

pem.EncodeToMemory(...) → test_pub.pem 저장
  • RSA 공개키는 (modulus, exponent) 만으로 구성됩니다. 

서명 검증 (verify.go) 

// 공개키 로딩
pub, _ := x509.ParsePKIXPublicKey(decodedPemBytes)
rsaPub := pub.(*rsa.PublicKey)

// 메시지 SHA256 해시
hashed := sha256.Sum256(msg)

// 서명 검증
rsa.VerifyPKCS1v15(rsaPub, crypto.SHA256, hashed[:], signature)

 

  • 서명 검증에 실패하면 "서명 불일치", 성공하면 "위변조 없음" 출력
  • sig_from_go.bin은 HSM의 RSA 개인키로 서명된 값이고, 공개키로만 검증 가능

결론

HSM은 키를 안전하게 보관하면서 외부에 노출되지 않도록 서명 작업을 내부에서 처리해주는 장비입니다.
Go 언어와 pkcs11 모듈을 활용하면, 이런 HSM 기반 키 관리와 서명 과정을 코드로 손쉽게 자동화할 수 있습니다.

이번 글에서는 HSM에서 RSA 키를 생성하고, Go로 메시지를 서명한 뒤 공개키를 추출해 서명을 검증하는 전체 흐름을 적어봤습니다. 
실제 운영 환경에서는 PIN 인증이나 세션 보안 같은 부분도 함께 신경 써야 한다는 점 참고하세요.

 

profile

클라우드 타고 포트와 파도

@cloudwave

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!