피로곰's 모두의 프린터

모두의 프린터는 개인, 기업 상관 없이 누구나 무료로 사용가능한 프로그램입니다. 회원가입,카드결제등을 요구하지 않습니다! 광고를 통해 연결되는 사이트에서의 회원가입, 카드결제 피해를 보지 않도록 주의하세요!
반응형

암호화 관련된 자료들은 워낙 찾아보면 많이 나오는 편이라서;; 근데 또 막상 찾아서 쓸라 하면 또 GPL이고 그래서 짜려니 귀찮고 그런경우가 많다 말이죠 ..

그런이유로 -_-;; 간단히 막 짜서 쓸려고 만든것좀 공유해 봅니다.

//
// Author: PIROGOM
// https://modu-print.tistory.com
// mop.pirogom@gmail.com
// MIT License
//
package main

import (
	"crypto/rand"
	"crypto/rsa"
	"crypto/x509"
	"encoding/hex"
	"encoding/pem"
	"errors"
	"io/ioutil"
)

type RSAHelper struct {
	PriKey *rsa.PrivateKey
	PubKey *rsa.PublicKey
}

/**
* RSA Key 생성
**/
func (r *RSAHelper) GenerateKey(bits int) error {
	privateKey, err := rsa.GenerateKey(rand.Reader, bits)

	if err != nil {
		r.PriKey = nil
		r.PubKey = nil
		return err
	}

	r.PriKey = privateKey
	r.PubKey = &privateKey.PublicKey

	return nil
}

func (r *RSAHelper) GetPrivate() *rsa.PrivateKey {
	return r.PriKey
}

func (r *RSAHelper) GetPublic() *rsa.PublicKey {
	return r.PubKey
}

/**
*	PrivateToBytePEM
*	PrivateToStringPEM
**/
func (r *RSAHelper) PrivateToBytePEM() ([]byte, error) {
	if r.PriKey == nil {
		return nil, errors.New("private rsa key is nil")
	}

	privateKeyBytes := x509.MarshalPKCS1PrivateKey(r.PriKey)
	privateKeyPEM := pem.EncodeToMemory(
		&pem.Block{
			Type:  "RSA PRIVATE KEY",
			Bytes: privateKeyBytes,
		},
	)
	return privateKeyPEM, nil
}

func (r *RSAHelper) PrivateToStringPEM() (string, error) {
	pemBuf, err := r.PrivateToBytePEM()

	if err != nil {
		return "", err
	}
	return string(pemBuf), nil
}

/**
*	PrivateFromBytePEM
*	PrivateFromFilePEM
**/
func (r *RSAHelper) PrivateFromBytePEM(privateKeyPEM []byte) error {
	block, _ := pem.Decode(privateKeyPEM)

	if block == nil {
		r.PriKey = nil
		return errors.New("invalid PEM Block(private key)")
	}

	privateKey, err := x509.ParsePKCS1PrivateKey(block.Bytes)

	if err != nil {
		r.PriKey = nil
		return err
	}

	r.PriKey = privateKey
	return nil
}

func (r *RSAHelper) PrivateFromStringPEM(privateKeyPEM string) error {
	return r.PrivateFromBytePEM([]byte(privateKeyPEM))
}

func (r *RSAHelper) PrivateFromFilePEM(filename string) error {
	fileBuf, err := ioutil.ReadFile(filename)
	if err != nil {
		return err
	}
	err = r.PrivateFromBytePEM(fileBuf)
	return err
}

/**
*	PublicToBytePEM
* 	PublicToStringPEM
**/
func (r *RSAHelper) PublicToBytePEM() ([]byte, error) {
	if r.PubKey == nil {
		return nil, errors.New("public rsa key is nil")
	}
	publicKeyBytes, err := x509.MarshalPKIXPublicKey(r.PubKey)
	if err != nil {
		return nil, err
	}
	publicKeyPEM := pem.EncodeToMemory(
		&pem.Block{
			Type:  "RSA PUBLIC KEY",
			Bytes: publicKeyBytes,
		},
	)
	return publicKeyPEM, nil
}

func (r *RSAHelper) PublicToStringPEM() (string, error) {
	buf, err := r.PublicToBytePEM()
	if err != nil {
		return "", err
	}
	return string(buf), nil
}

/**
*	PublicFromBytePEM
**/
func (r *RSAHelper) PublicFromBytePEM(publicKeyPEM []byte) error {
	block, _ := pem.Decode(publicKeyPEM)
	if block == nil {
		r.PubKey = nil
		return errors.New("invalid PEM Block (public key)")
	}

	publicKey, err := x509.ParsePKIXPublicKey(block.Bytes)
	if err != nil {
		r.PubKey = nil
		return err
	}

	switch pub := publicKey.(type) {
	case *rsa.PublicKey:
		r.PubKey = pub
		return nil
	default:
		return errors.New("invalid key type")
	}
}

func (r *RSAHelper) PublicFromStringPEM(publicKeyPEM []byte) error {
	return r.PublicFromBytePEM([]byte(publicKeyPEM))
}

func (r *RSAHelper) PublicFromFilePEM(filename string) error {
	fileBuf, err := ioutil.ReadFile(filename)
	if err != nil {
		return err
	}
	err = r.PublicFromBytePEM(fileBuf)
	return err
}

/**
*	EncryptByte
**/
func (r *RSAHelper) EncryptByte(src []byte) ([]byte, error) {

	if r.PubKey == nil {
		return nil, errors.New("public key is nil")
	}

	ciphertext, err := rsa.EncryptPKCS1v15(rand.Reader, r.PubKey, src)

	if err != nil {
		return nil, err
	}
	return ciphertext, nil
}

func (r *RSAHelper) EncryptString(src string) (string, error) {
	enc, err := r.EncryptByte([]byte(src))
	if err != nil {
		return "", err
	}
	return hex.EncodeToString(enc), nil
}

/**
* DecryptByte
**/
func (r *RSAHelper) DecryptByte(src []byte) ([]byte, error) {

	if r.PriKey == nil {
		return nil, errors.New("private key is nil")
	}

	plaintext, err := rsa.DecryptPKCS1v15(rand.Reader, r.PriKey, src)

	if err != nil {
		return nil, err
	}
	return plaintext, nil
}

func (r *RSAHelper) DecryptString(src string) (string, error) {
	bsrc, err := hex.DecodeString(src)
	if err != nil {
		return "", err
	}
	dec, err := r.DecryptByte(bsrc)

	if err != nil {
		return "", err
	}

	return string(dec), nil
}

RSAHelper 라는 구조체와 그 구조체에 딸린 메소드들입니다. 

package main

import "fmt"

func main() {
	rh := RSAHelper{}
	rh.GenerateKey(1024)

	priv_pem, _ := rh.PrivateToStringPEM()
	pub_pem, _ := rh.PublicToStringPEM()

	fmt.Println(priv_pem)
	fmt.Println(pub_pem)

	s := "PIROGOM|hahahaha|panichwanja|20220303"

	fmt.Println("plain", s)

	enc, _ := rh.EncryptString(s)

	fmt.Println(enc)

	dec, _ := rh.DecryptString(enc)

	fmt.Println(dec)
}

이런식으로 쓰시면 되겠습니다. 예제에선 오류체크를 전혀 안하고 있는데 .. 별로 좋은 습관은 아닌거 아시죠? ㅋㅋ 뭔가 잘 안될떈 _ 로 무시중인 error 리턴 값들을 확인 바랍니다.

GenerateKey 함수의 인자는 몇비트로 키를 만들꺼냐의 문제인데 값이 크면 클수록 키 생성과 암호화, 복호화에 시간이 많이 소요됩니다. 

나머지는 그리 어려운 구조의 코드는 아니니까 ;; 

필요하면 가따 쓰소서~ 

반응형

공유하기

facebook twitter kakaoTalk kakaostory naver band