앞서서(1장에서) 암호화에 대해서 기본 개념을 살펴보았는데 참고하지 못했다면 아래포스팅을 꼭 읽고 2장을 보도록 하자
https://joylucky7.tistory.com/44
◆ AES 대칭키 알고리즘
▶ crypto / aes 패키지의 함수
● func NewCipher(key []byte) (cipher.Block, error): 대칭키 암호화 블록 생성
● func (c *aesCipher) Encrypt(dst, src []byte): 평문을 AES 알고리즘으로 암호화
● func (c *aesCipher) Decrypt(dst, src []byte): AES 알고리즘으로 암호화된 데이터를 평문으로 복호화
▶ 암호화 와 복호화
package main
import (
"crypto/aes"
"fmt"
)
func main() {
key := "Hello, Key 12345" // 16바이트
s := "Hello, world! 12" // 16바이트
block, err := aes.NewCipher([]byte(key)) // AES 대칭키 암호화 블록 생성
if err != nil {
fmt.Println(err)
return
}
ciphertext := make([]byte, len(s))
block.Encrypt(ciphertext, []byte(s)) // 평문을 AES 알고리즘으로 암호화
fmt.Printf("%x\n", ciphertext)
plaintext := make([]byte, len(s))
block.Decrypt(plaintext, ciphertext) // AES 알고리즘으로 암호화된 데이터를 평문으로 복호화
fmt.Println(string(plaintext))
}
▶ crypto / cipher 패키지의 CBC(Ciper Block Chaning) 함수
● func NewCBCEncrypter(b Block, iv []byte) BlockMode: 암호화 블록과 초기화 벡터로 암호화 블록 모드 인스턴스 생성
● func (x *cbcEncrypter) CryptBlocks(dst, src []byte): 암호화 블록 모드 인스턴스로 암호화
● func NewCBCDecrypter(b Block, iv []byte) BlockMode: 암호화 블록과 초기화 벡터로 복호화 블록 모드 인스턴스 생성
● func (x *cbcDecrypter) CryptBlocks(dst, src []byte): 복호화 블록 모드 인스턴스로 복호화
package main
import (
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"fmt"
"io"
)
func encrypt(b cipher.Block, plaintext []byte) []byte {
if mod := len(plaintext) % aes.BlockSize; mod != 0 { // 블록 크기의 배수가 되어야함
padding := make([]byte, aes.BlockSize-mod) // 블록 크기에서 모자라는 부분을
plaintext = append(plaintext, padding...) // 채워줌
}
ciphertext := make([]byte, aes.BlockSize+len(plaintext)) // 초기화 벡터 공간(aes.BlockSize)만큼 더 생성
iv := ciphertext[:aes.BlockSize] // 부분 슬라이스로 초기화 벡터 공간을 가져옴
if _, err := io.ReadFull(rand.Reader, iv); err != nil { // 랜덤 값을 초기화 벡터에 넣어줌
fmt.Println(err)
return nil
}
mode := cipher.NewCBCEncrypter(b, iv) // 암호화 블록과 초기화 벡터를 넣어서 암호화 블록 모드 인스턴스 생성
mode.CryptBlocks(ciphertext[aes.BlockSize:], plaintext) // 암호화 블록 모드 인스턴스로
// 암호화
return ciphertext
}
func decrypt(b cipher.Block, ciphertext []byte) []byte {
if len(ciphertext)%aes.BlockSize != 0 { // 블록 크기의 배수가 아니면 리턴
fmt.Println("암호화된 데이터의 길이는 블록 크기의 배수가 되어야합니다.")
return nil
}
iv := ciphertext[:aes.BlockSize] // 부분 슬라이스로 초기화 벡터 공간을 가져옴
ciphertext = ciphertext[aes.BlockSize:] // 부분 슬라이스로 암호화된 데이터를 가져옴
plaintext := make([]byte, len(ciphertext)) // 평문 데이터를 저장할 공간 생성
mode := cipher.NewCBCDecrypter(b, iv) // 암호화 블록과 초기화 벡터를 넣어서
// 복호화 블록 모드 인스턴스 생성
mode.CryptBlocks(plaintext, ciphertext) // 복호화 블록 모드 인스턴스로 복호화
return plaintext
}
func main() {
key := "Hello Key 123456" // 16바이트
s := `동해 물과 백두산이 마르고 닳도록
하느님이 보우하사 우리나라 만세.
무궁화 삼천리 화려강산
대한 사람, 대한으로 길이 보전하세.`
block, err := aes.NewCipher([]byte(key)) // AES 대칭키 암호화 블록 생성
if err != nil {
fmt.Println(err)
return
}
ciphertext := encrypt(block, []byte(s)) // 평문을 AES 알고리즘으로 암호화
fmt.Printf("%x\n", ciphertext)
plaintext := decrypt(block, ciphertext) // AES 알고리즘 암호문을 평문으로 복호화
fmt.Println(string(plaintext))
}
◆ RSA 공개키 알고리즘
▶ crypto / rsa 패키지의 함수
● func GenerateKey(random io.Reader, bits int) (priv *PrivateKey, err error): 개인키와 공개키 생성
● func EncryptPKCS1v15(rand io.Reader, pub *PublicKey, msg [ ]byte) (out []byte, err error): 평문을 공개키로 암호화
● func DecryptPKCS1v15(rand io.Reader, priv *PrivateKey, ciphertext []byte) (out []byte, err error): 암호화된 데이터를 개인키로 복호화
package main
import (
"crypto/rand"
"crypto/rsa"
"fmt"
)
func main() {
privateKey, err := rsa.GenerateKey(rand.Reader, 2048) // 개인 키와 공개키 생성
if err != nil {
fmt.Println(err)
return
}
publicKey := &privateKey.PublicKey // 개인 키 변수 안에 공개 키가 들어있음
s := `동해 물과 백두산이 마르고 닳도록
하느님이 보우하사 우리나라 만세.
무궁화 삼천리 화려강산
대한 사람, 대한으로 길이 보전하세.`
ciphertext, err := rsa.EncryptPKCS1v15( // 평문을 공개 키로 암호화
rand.Reader,
publicKey, // 공개키
[]byte(s),
)
fmt.Printf("%x\n", ciphertext)
plaintext, err := rsa.DecryptPKCS1v15( // 암호화된 데이터를 개인 키로 복호화
rand.Reader,
privateKey, // 개인키
ciphertext,
)
fmt.Println(string(plaintext))
}
▶ crypto / rsa 패키지의 서명 / 인증 함수
● func SignPKCS1v15(rand io.Reader, priv *PrivateKey, hash crypto.Hash, hashed []byte) (s []byte, err error): 개인키로 서명
● func VerifyPKCS1v15(pub *PublicKey, hash crypto.Hash, hashed []byte, sig []byte) (err error): 공개키로 서명 검증
▶ crypto / rsa 패키지의 해시 함수
● func New() hash.Hash: MD5 해시 인스턴스 생성
● func (d *digest) Write(p []byte) (nn int, err error): 해시 인스턴스에 데이터 추가ㅍ
● func (d0 *digest) Sum(in []byte) []byte: 해시 인스턴스에 저장된 데이터의 MD5 해시 값 추출
▶ 서명
package main
import (
"crypto"
"crypto/md5"
"crypto/rand"
"crypto/rsa"
"fmt"
)
func main() {
privateKey, err := rsa.GenerateKey(rand.Reader, 2048) // 개인 키와 공개 키 생성
if err != nil {
fmt.Println(err)
return
}
publicKey := &privateKey.PublicKey // 개인 키 변수 안에 공개 키가 들어있음
message := "안녕하세요. Go 언어"
hash := md5.New() // 해시 인스턴스 생성
hash.Write([]byte(message)) // 해시 인스턴스에 문자열 추가
digest := hash.Sum(nil) // 문자열의 MD5 해시 값 추출
var h1 crypto.Hash
signature, err := rsa.SignPKCS1v15( // 개인 키로 서명
rand.Reader,
privateKey, // 개인 키
h1,
digest, // MD5 해시 값
)
var h2 crypto.Hash
err = rsa.VerifyPKCS1v15( // 공개 키로 서명 검증
publicKey, // 공개 키
h2,
digest, // MD5 해시 값
signature, // 서명 값
)
if err != nil {
fmt.Println("검증 실패")
} else {
fmt.Println("검증 성공")
}
}
'IT 초보코딩의 세계 > Go 언어' 카테고리의 다른 글
[Block Chain] Go언어의 RESTful API, Gin Framework, Model&Database Layer 1장 (12) | 2023.04.15 |
---|---|
[Block Chain] Go언어의 Web Download 3장 (0) | 2023.04.14 |
[Block Chain] Go언어의 JSON, 암호화 1장 (0) | 2023.04.14 |
Go언어의 출력함수 IO, 파일 입출력, ioutil패키지 3장 (2) | 2023.04.12 |
Go언어의 출력함수 IO, 문자열 처리 및 조작, 정규식 2장 (7) | 2023.04.11 |
댓글