비 대칭키 알고리즘은 공개키 비밀키로 키를 분리하여, 공개키로 암/복호화에 두 키가 요구되는 알고리즘 입니다.
서명, 키 교환 데이터 검증 등 에 사용되며 go
언어는 다양한 비 대칭키 알고리즘을 지원합니다.
이번에는 rsa
알고리즘을 다루겠습니다.
rsa
dsa
ecdsa
ed25519
RSA
비밀키
암호화, 복호화, 서명, 검증 알고리즘을 지원합니다.
다음 명령어로 rsa
알고리즘의 비밀키를 생성합니다.
priv, err := rsa.GenerateKey(rand.Reader, 2048) // 랜덤값 리더, 키 길이
인자로 랜덤 값 리더 키 길이를 입력합니다. 랜덤 값 리더는 go
에서 기본 제공하는 rand.Reader
를 사용합니다.
rand.Reader
는 운용 환경에 따라 적절한 랜덤 시스템 콜을 호출해 줍니다.
공개키
공개키는 비밀키 구조체에 다음 형태로 존재합니다.
priv, _ := rsa.GenerateKey(rand.Reader, 2048) // 랜덤값 리더, 키 길이
pub := priv.PublicKey
공개키로 암호화
다음 함수로 rsa
공개키로 평문을 암호화 합니다.
ciphertext, err := rsa.EncryptPKCS1v15(rand.Reader, &pub, msg)
// 랜덤값 리더, 공개키, 평문
// 암호화 예제
package main
import (
"crypto/rand"
"crypto/rsa"
"fmt"
)
func main() {
priv, _ := rsa.GenerateKey(rand.Reader, 2048)
pub := priv.PublicKey
msg := []byte("i am plain text")
ciphertext, _ := rsa.EncryptPKCS1v15(rand.Reader, &pub, msg)
fmt.Printf("%x\n", ciphertext)
}
// 출력
7d19b3d1cd745946915a3cd5a9b0441bf6a676230d5029dbb275d750e1db13d2ba278bb3e7eed2ea25e16bdb7981f113d586b4a84e344e0f33f1cce275bb21f54bba5c9700d3ceed1712e3142040e90976824f295a553333f4baff1bb884e8999f6beba39efce336b3aa7db2805cbb5828e455d7e93b65517c614ebfa5373ed513b346ee231aaafc43a0fe9d50a107101c839913399e4071cd30f2359481ae518c653d31b46ee84ad0b9fe2b4bcaa355da72a3ea21ed7f13e96c56a8235c83af39de574e9efa6a98bea979aacb9e0a99a5a9e90ff1dc4ae8f47bad91a176859c45ea071fc2c334fb6898bb6bee30c64e503e12c0dc748ffcbf7ccea953fad447
출력은 매 실행마다 달라집니다.
비밀키로 복호화
다음 함수로 암호문을 복호화 합니다.
plaintext, err := rsa.DecryptPKCS1v15(rand.Reader, priv, ciphertext)
// 랜덤값 리더, 비밀키, 암호문
// 복호화 예제
package main
import (
"crypto/rand"
"crypto/rsa"
"fmt"
)
func main() {
priv, _ := rsa.GenerateKey(rand.Reader, 2048)
pub := priv.PublicKey
msg := []byte("i am plain text")
ciphertext, _ := rsa.EncryptPKCS1v15(rand.Reader, &pub, msg)
fmt.Printf("%x\n", ciphertext)
plaintext, _ := rsa.DecryptPKCS1v15(rand.Reader, priv, ciphertext)
fmt.Printf("%s\n", plaintext)
}
// 출력
8366c8e6c2acf9ffb7fc3b9c2059b3067a209eae2a9c60a1c4dc691d9ed7e767f2db08cec0538cdec3abcdcc7a4c4b3d9357b9dffb9898f6d81aaaaf9166fa50137e6ff89add8679980520988b4b79ef7380a76910060fe27f577180c55df866a5f20477fdb932c5d0a1318bed0263db9f132f3d58aeb1304b62e030295afa34bffc696a90e462c58bf0771ef8453a91c531bd1fcfd3d97b3798f3ea8a4b9baea4866435c03e04f2704b65177a9786779ab7bff8f5f6db4ebf38c294f1b1088d5b0dc24118bf27cc1858c07ec2986ca88fdfc5d41890eb92d55c6a771830e57c853bb36dc7834b9e677be1e6b2a9bfe6c7617d54fa836f51126c4e34dcd08ed3
i am plain text
OAEP 암/복호화
Optimal Asymmetric Encryption Padding (OAEP)
rsa
에 패딩과 추가적인 연산으로 암호문으로 평문을 예상할 수 없도록 보안성이 강화된 알고리즘 입니다.
OAEP
암/복호화에는 다음 함수가 사용됩니다.
ciphertext, _ := rsa.EncryptOAEP(sha256.New(), rand.Reader, &pub, msg, nil)
// 사용할 해시, 랜덤 리더, 공개키, 평문, OAEP 레이블
plaintext, _ := rsa.DecryptOAEP(sha256.New(), rand.Reader, priv, ciphertext, nil)
// 사용할 해시, 랜덤 리더, 비밀키, 비문, OAEP 레이블
해시 함수는 보통 SHA256
이 사용됩니다.
// OAEP 암/복호화 예제
package main
import (
"crypto/rand"
"crypto/rsa"
"crypto/sha256"
"fmt"
)
func main() {
priv, _ := rsa.GenerateKey(rand.Reader, 2048)
pub := priv.PublicKey
msg := []byte("i am plain text")
ciphertext, _ := rsa.EncryptOAEP(sha256.New(), rand.Reader, &pub, msg, nil)
fmt.Printf("%x\n", ciphertext)
plaintext, _ := rsa.DecryptOAEP(sha256.New(), rand.Reader, priv, ciphertext, nil)
fmt.Printf("%s\n", plaintext)
}
// 결과
9e122ce4d4deffc5f8750b8339bacb874d17bfb91270539426176adae34a76317f58ecf17b425c1731c15b4f88a3b8846a448aaa8e6df6ea991748185becada497ccefdb75c7c1fac31ea75d8c80907836f9a6a9b384161296b0ed616c5e0a8ce378f620e20f35e513fe990f2c20848f4eba6cf411d7a1aaecfe186ff50a4b9717c78dfc5702a64c0393df1e0c44663853afb511d1eac94574b811ceca21fb74e46993d6fccf394a02ebde5e9c9451482138aaa29b66558ada5fea449465535c8b41080fa88506e033c52e3e58054f4905b50b5770737cad5cf7dd479c2ce8f31718ce423f9455df69a64a1096c3dea86c6d893bf6ae37e0ec5830c7647c8a26
i am plain text