안드로이드 앱이랑 golang이랑 통신할때 암호화 할려고 golang에서 rsa 쓰는법 연습하던거 여기 정리해둠.
privateKey, err := rsa.GenerateKey(rand.Reader, 2048) if err != nil { log.Println("error : ", err) } publicKey := &privateKey.PublicKey
Golang에서 RSA-2048로 publcKey와 privateKey 생성은 위와 같이 간단하다.
var text = "동해물과 백두산이" fmt.Println("원본 : ", text) //공개키로 문자열을 암호화 한다. encText, err := rsa.EncryptPKCS1v15(rand.Reader, publicKey, []byte(text)) if err != nil { log.Println("error : ", err) } //base64로 인코딩 하는건 디버그 출력으로 보거나 통신할때 쓸려고 하는것이지 굳이 안해도 되긴함. encTextStr := base64.StdEncoding.EncodeToString(encText) fmt.Println("암호화 : ", encTextStr) //base64로 인코딩한거 다시 디코딩해주고 개인키로 복호화를 한다. encText2, _ := base64.StdEncoding.DecodeString(encTextStr) decText, err := rsa.DecryptPKCS1v15(rand.Reader, privateKey, encText2) if err != nil { log.Println("error : ", err) } fmt.Println("복호화 : ", string(decText))
golang용 rsa 라이브러리는 privateKey로 암호화(Encrypt) 하거나 publicKey로 복호화(decrypt) 되지 않음. 안드로이드쪽에서 쓰는 java.security패키지에서는 키 종류와 상관없이 되는데 처음에는 golang에 뭔가 문제가 있는줄 알았지만 검색해보고 golang쪽이 근본적인 논리로는 맞는 방식임.
publicKey는 누구나 볼수 있는 키인데 privateKey로 암호화 하면 그 암호문은 의미가 없어짐
암호화 알고리즘적으로도 문제가 있다는 댓글을 보긴 했는데 이건 잘 모르겠음.
안드로이드에서 RSA 사용할때 위와 같은 패딩 선택하는게 있었는데 PKCS1Padding을 선택했을때 위와 같은 Encrypt, Decrypt를 쓰는거고 OAEP 패딩을 선택했다면
encText, err := rsa.EncryptOAEP(sha1.New(), rand.Reader, publicKey, []byte(text)) decText, err := rsa.DecryptOAEP(sha1.New(), rand.Reader, privateKey, encText2)
이 함수를 써야 한다.
그리고 패딩에 보면 SHA-1, SHA-256, SHA-512… 있는데 여기에 맞게 EncryptOAEP, DecryptOAEP 첫번째 인자를 sha1, sha256, sha512로 바꿔줘야 한다.
OAEPwithSHA-224andMGF1Padding 는 sha256.New224() OAEPwithSHA-384andMGF1Padding 는 sha512.New384()
224랑 384는 위와 같다.
func PEMtoPublicKey(pubPEM string) (*rsa.PublicKey, error) { block, _ := pem.Decode([]byte(pubPEM)) if block == nil { return nil, errors.New("PEM 파싱에 실패했습니다.") } pub, err := x509.ParsePKIXPublicKey(block.Bytes) if err != nil { return nil, err } switch pub := pub.(type) { case *rsa.PublicKey: return pub, nil default: break } return nil, errors.New("키가 RSA 타입이 아닙니다.") }
“—–BEGIN PUBLIC KEY—–” 으로 시작하는 PEM 방식을 Golang publicKey로 바꾸는 함수임.
키값 전송할때 —–로 시작하는 문구를 쓰지 않고 키만 직접 전송한다면
func PEMtoPublicKey(pubPEM string) (*rsa.PublicKey, error) { tmpStr, err := base64.StdEncoding.DecodeString(pubPEM) if err != nil { return nil, err } pub, err := x509.ParsePKIXPublicKey(tmpStr) if err != nil { return nil, err } switch pub := pub.(type) { case *rsa.PublicKey: return pub, nil default: break } return nil, errors.New("키가 RSA 타입이 아닙니다.") }
이런식으로 바꾸면 된다.
func PEMtoPrivateKey(pubPEM string) (*rsa.PrivateKey, error) { block, _ := pem.Decode([]byte(pubPEM)) if block == nil { return nil, errors.New("PEM 파싱에 실패했습니다.") } pri, err := x509.ParsePKCS1PrivateKey(block.Bytes) if err != nil { return nil, err } return pri, nil }
이건 PrivateKey를 변환할때 사용되고 마찬가지로 —– 부분을 쓰지 않는다면 pem.Decode 부분을 바꾸면 된다.
답글 남기기