피로곰's 모두의 프린터

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

특정 데이터의 유효성 검증을 위해서 만든 메소드들입니다. 원래 ECDSA 를 사용하는 놈으로 만들었다가 키를 만드는데 사용되는 P256.. 등의 P시리즈 커브들이 이래저래 말들이 많아서 ED25519를 사용하는 방식으로 변경하였습니다.

ED25519 나 ECDSA는 데이터를 암호화하고 복호화하는데 사용되는게 아니라 특정 데이터에 개인키로 서명(Sign)을 하고 공개키로 서명이 유효한지를 검증해주는 방식으로 사용합니다.

예를들어 데이터가 "피로곰"인 경우에 서버에서 "피로곰"에 개인키로 서명을하고 서명되고 암호화된 데이터를 클라이언트에 전송하면 클라이언트에서는 "피로곰"과 서버에서 보내준 서명된 데이터를 가지고 공개키로 검증을 합니다. 

애초에 사인하기 전의 원본 데이터를 모르거나 원본데이터를 알아도 서명이 검증되지 못하면 문제 있는 데이터가 되버리는 것이지요..

내가 알고 있는 이 값이 .. 정말 상대가 보낸 값이 맞는가를 검증하는데 사용하시면 되겠습니다.

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

import (
	"crypto/ed25519"
	"crypto/rand"
	"crypto/sha256"
	"encoding/hex"
	"encoding/pem"
	"errors"
	"fmt"
	"io/ioutil"
)

type ECDSAHelper struct {
	PrivateKey *ed25519.PrivateKey
	PublicKey  *ed25519.PublicKey
}

/**
*	Generate
**/
func (e *ECDSAHelper) Generate() error {

	if e.PrivateKey != nil {
		e.PrivateKey = nil
		e.PublicKey = nil
	}

	publicKey, privateKey, err := ed25519.GenerateKey(rand.Reader)

	if err != nil {
		return err
	}

	e.PrivateKey = &privateKey
	e.PublicKey = &publicKey
	return nil
}

/**
*	EncodePrivateKey
**/
func (e *ECDSAHelper) EncodePrivateKey() ([]byte, error) {
	if e.PrivateKey == nil {
		return nil, errors.New("private key is nil")
	}

	encBuf := pem.EncodeToMemory(
		&pem.Block{
			Type:  "ED25519 PRIVATE KEY",
			Bytes: *e.PrivateKey,
		})

	return encBuf, nil
}

/**
*	DecodePrivateKey
**/
func (e *ECDSAHelper) DecodePrivateKey(encKey []byte) error {
	if e.PrivateKey != nil {
		e.PrivateKey = nil
	}

	block, _ := pem.Decode(encKey)

	if block == nil {
		return errors.New("failed to find ED25519 PRIVATE KEY")
	}

	if block.Type != "ED25519 PRIVATE KEY" {
		return fmt.Errorf("%s is invalid block type", block.Type)
	}
	e.PrivateKey = (*ed25519.PrivateKey)(&block.Bytes)
	return nil
}

/**
*	PrivateKeyToFile
**/
func (e *ECDSAHelper) PrivateKeyToFile(fname string) error {
	if e.PrivateKey == nil {
		return errors.New("private key is nil")
	}
	enc, err := e.EncodePrivateKey()

	if err != nil {
		return err
	}

	err = ioutil.WriteFile(fname, enc, 0644)

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

/**
*	PrivateKeyFromFile
**/
func (e *ECDSAHelper) PrivateKeyFromFile(fname string) error {
	if e.PrivateKey != nil {
		e.PrivateKey = nil
	}

	buf, err := ioutil.ReadFile(fname)

	if err != nil {
		return err
	}

	err = e.DecodePrivateKey(buf)

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

/**
*	EncodePublicKey
**/
func (e *ECDSAHelper) EncodePublicKey() ([]byte, error) {
	if e.PublicKey == nil {
		return nil, errors.New("public key is nil")
	}

	encBuf := pem.EncodeToMemory(
		&pem.Block{
			Type:  "ED25519 PUBLIC KEY",
			Bytes: *e.PublicKey,
		})

	return encBuf, nil
}

/**
*	DecodePublicKey
**/
func (e *ECDSAHelper) DecodePublicKey(encKey []byte) error {
	if e.PublicKey != nil {
		e.PublicKey = nil
	}

	block, _ := pem.Decode(encKey)

	if block == nil {
		return errors.New("failed to find ED25519 PUBLIC KEY")
	}

	if block.Type != "ED25519 PUBLIC KEY" {
		return fmt.Errorf("%s is invalid block type", block.Type)
	}

	e.PublicKey = (*ed25519.PublicKey)(&block.Bytes)

	return nil
}

/**
*	PublicKeyToFile
**/
func (e *ECDSAHelper) PublicKeyToFile(fname string) error {
	if e.PublicKey == nil {
		return errors.New("public key is nil")
	}
	enc, err := e.EncodePublicKey()

	if err != nil {
		return err
	}

	err = ioutil.WriteFile(fname, enc, 0644)

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

/**
*	PublicKeyFromFile
**/
func (e *ECDSAHelper) PublicKeyFromFile(fname string) error {
	if e.PublicKey != nil {
		e.PrivateKey = nil
	}

	buf, err := ioutil.ReadFile(fname)

	if err != nil {
		return err
	}

	err = e.DecodePublicKey(buf)

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

/**
*	Sign
**/
func (e *ECDSAHelper) Sign(msg string) ([]byte, error) {
	if e.PrivateKey == nil {
		return nil, errors.New("private key is nil")
	}

	hash := sha256.Sum256([]byte(msg))
	signed := ed25519.Sign(*e.PrivateKey, hash[:])

	return signed, nil
}

/**
*	SignToString
**/
func (e *ECDSAHelper) SignToString(msg string) (string, error) {
	signed, err := e.Sign(msg)

	if err != nil {
		return "", err
	}
	return hex.EncodeToString(signed), nil
}

/**
* SignToPEM
**/
func (e *ECDSAHelper) SignToPEM(msg string, blockType string) ([]byte, error) {
	signed, err := e.Sign(msg)

	if err != nil {
		return nil, err
	}

	encBuf := pem.EncodeToMemory(
		&pem.Block{
			Type:  blockType,
			Bytes: signed,
		})

	return encBuf, nil
}

/**
*	SignFromPEM
**/
func (e *ECDSAHelper) SignFromPEM(pemBuf []byte, blockType string) ([]byte, error) {
	block, _ := pem.Decode(pemBuf)

	if block == nil {
		return nil, errors.New("failed to find ED25519 PUBLIC KEY")
	}

	if block.Type != blockType {
		return nil, fmt.Errorf("%s is invalid block type", block.Type)
	}

	return block.Bytes, nil
}

/**
*	IsValidSignPEM
**/
func (e *ECDSAHelper) IsValidSignPEM(pemBuf []byte, blockType string) bool {
	block, _ := pem.Decode(pemBuf)

	if block == nil {
		return false
	}

	if block.Type != blockType {
		return false
	}
	return true
}

/**
*	Verify
**/
func (e *ECDSAHelper) Verify(msg string, signed []byte) bool {
	if e.PublicKey == nil {
		return false
	}
	hash := sha256.Sum256([]byte(msg))

	return ed25519.Verify(*e.PublicKey, hash[:], signed)
}

/**
*	VerifyString
**/
func (e *ECDSAHelper) VerifyString(msg string, signed string) bool {
	byteSigned, err := hex.DecodeString(signed)

	if err != nil {
		return false
	}

	return e.Verify(msg, byteSigned)
}

 

반응형

공유하기

facebook twitter kakaoTalk kakaostory naver band