Denmaseno 7 lat temu
commit
8a690f8f34
7 zmienionych plików z 804 dodań i 0 usunięć
  1. 102 0
      encrypter/aes.go
  2. 31 0
      encrypter/rsa-encrypted.go
  3. 295 0
      encrypter/rsa.go
  4. 108 0
      signer/signature.go
  5. 83 0
      slog/formatter.go
  6. 177 0
      slog/slog.go
  7. 8 0
      util/util.go

+ 102 - 0
encrypter/aes.go

@@ -0,0 +1,102 @@
+package encrypter
+
+import (
+	"crypto/aes"
+	"crypto/cipher"
+	"crypto/rand"
+	"crypto/rsa"
+	"crypto/sha256"
+	"encoding/base64"
+)
+
+// AESKey type
+type AESKey []byte
+
+// EncryptedAESKey type
+type EncryptedAESKey []byte
+
+// NewAESKey func
+func NewAESKey() AESKey {
+	bb := make([]byte, 32)
+	rand.Read(bb)
+	return AESKey(bb)
+}
+
+// ParseAESKey func
+func ParseAESKey(b []byte) AESKey {
+	if len(b) != 32 {
+		slog.Panicf("Invalid AESKey (%v)", len(b))
+	}
+	return (AESKey)(b)
+}
+
+// EncryptKey func
+func (s *AESKey) EncryptKey(key *PublicKey) EncryptedAESKey {
+	bb, err := key.Encrypt(([]byte)(*s))
+	if err != nil {
+		panic(err)
+	}
+	return (EncryptedAESKey)(bb)
+}
+
+// Encrypt func
+func (s *AESKey) Encrypt(data []byte) (encrypted []byte, err error) {
+	nonce := make([]byte, 12)
+	rand.Read(nonce)
+	block, err := aes.NewCipher(([]byte)(*s))
+	if err != nil {
+		slog.Warnf("ERROR New cipher %v", err)
+		return
+	}
+	gcm, err := cipher.NewGCM(block)
+	if err != nil {
+		slog.Warnf("ERROR New GCM %v", err)
+		return
+	}
+	encrypted = append(nonce, gcm.Seal(nil, nonce, data, nil)...)
+	return
+}
+
+// Decrypt func
+func (s *AESKey) Decrypt(data []byte) (plain []byte, err error) {
+	block, err := aes.NewCipher(([]byte)(*s))
+	if err != nil {
+		slog.Warnf("ERROR New cipher %v", err)
+		return
+	}
+	gcm, err := cipher.NewGCM(block)
+	if err != nil {
+		slog.Warnf("ERROR New GCM %v", err)
+		return
+	}
+	plain, err = gcm.Open(nil, data[:12], data[12:], nil)
+	return
+}
+
+// MarshalJSON func
+func (s *AESKey) MarshalJSON() ([]byte, error) {
+	return []byte("\"" + base64.RawURLEncoding.EncodeToString(([]byte)(*s)) + "\""), nil
+}
+
+func (s *AESKey) String() string {
+	return base64.RawURLEncoding.EncodeToString(*s)
+}
+
+// Decrypt func
+func (s *EncryptedAESKey) Decrypt(key *PrivateKey) (AESKey, error) {
+	bb, err := rsa.DecryptOAEP(sha256.New(), rand.Reader, (*rsa.PrivateKey)(key), ([]byte)(*s), nil)
+	if err != nil {
+		slog.Warnf("ERROR Decrypt %v", err)
+		return nil, err
+	}
+	return (AESKey)(bb), nil
+}
+
+// MarshalJSON func
+func (s *EncryptedAESKey) MarshalJSON() ([]byte, error) {
+	return []byte("\"" + base64.RawURLEncoding.EncodeToString(([]byte)(*s)) + "\""), nil
+}
+
+func (s *EncryptedAESKey) String() string {
+	return "\"" + base64.RawURLEncoding.EncodeToString(*s) + "\""
+}

+ 31 - 0
encrypter/rsa-encrypted.go

@@ -0,0 +1,31 @@
+package encrypter
+
+import (
+	"crypto/x509"
+	"encoding/base64"
+)
+
+// EncryptedPrivateKey type
+type EncryptedPrivateKey []byte
+
+// DecryptKey func
+func (s *EncryptedPrivateKey) DecryptKey(key *PrivateKey) (*PrivateKey, error) {
+	bb, err := key.Decrypt(([]byte)(*s))
+	if err != nil {
+		return nil, err
+	}
+	k, err := x509.ParsePKCS1PrivateKey(bb)
+	if err != nil {
+		return nil, err
+	}
+	return (*PrivateKey)(k), nil
+}
+
+// MarshalJSON func
+func (s *EncryptedPrivateKey) MarshalJSON() ([]byte, error) {
+	return []byte("\"" + base64.RawURLEncoding.EncodeToString(([]byte)(*s)) + "\""), nil
+}
+
+func (s *EncryptedPrivateKey) String() string {
+	return base64.RawURLEncoding.EncodeToString(*s)
+}

+ 295 - 0
encrypter/rsa.go

@@ -0,0 +1,295 @@
+package encrypter
+
+import (
+	"crypto/rand"
+	"crypto/rsa"
+	"crypto/sha256"
+	"crypto/x509"
+	"encoding/base64"
+	"fmt"
+	"reflect"
+	"strings"
+
+	msgpack "gopkg.in/vmihailenco/msgpack.v2"
+)
+
+// PrivateKey type
+type PrivateKey rsa.PrivateKey
+
+// PublicKey type
+type PublicKey rsa.PublicKey
+
+const (
+	keySize          = 2048
+	decryptBlockSize = 256
+	encryptBlockSize = 190
+)
+
+// NewPrivateKey func
+func NewPrivateKey() *PrivateKey {
+	pk, err := rsa.GenerateKey(rand.Reader, keySize)
+	if err != nil {
+		panic(fmt.Errorf("Error create rsa.PrivateKey %v", err))
+	}
+	return (*PrivateKey)(pk)
+}
+
+// ParsePrivateKey func
+func ParsePrivateKey(raw []byte) *PrivateKey {
+	k, err := x509.ParsePKCS1PrivateKey(raw)
+	if err != nil {
+		panic(fmt.Errorf("Error parse privateKey %v", err))
+	}
+	return (*PrivateKey)(k)
+}
+
+// ParsePrivateKeyString func
+func ParsePrivateKeyString(str string) (*PrivateKey, error) {
+	raw, err := base64.RawURLEncoding.DecodeString(str)
+	if err != nil {
+		slog.Debugf("Error key decode %v", err)
+		return nil, err
+	}
+	k, err := x509.ParsePKCS1PrivateKey(raw)
+	if err != nil {
+		slog.Debugf("Error parse key %v", err)
+		return nil, err
+	}
+	return (*PrivateKey)(k), nil
+}
+
+// ParsePublicKey func
+func ParsePublicKey(raw []byte) *PublicKey {
+	k, err := x509.ParsePKIXPublicKey(raw)
+	if err != nil {
+		panic(fmt.Errorf("Error parse privateKey %v", err))
+	}
+	if p, ok := k.(*rsa.PublicKey); ok {
+		return (*PublicKey)(p)
+	}
+	panic(fmt.Errorf("Invalid type %s", reflect.TypeOf(k).String()))
+}
+
+// ParsePublicKeyString func
+func ParsePublicKeyString(str string) (*PublicKey, error) {
+	raw, err := base64.RawURLEncoding.DecodeString(str)
+	if err != nil {
+		slog.Debugf("Error key decode %v", err)
+		return nil, err
+	}
+	k, err := x509.ParsePKIXPublicKey(raw)
+	if err != nil {
+		slog.Debugf("Error parse key %v", err)
+		return nil, err
+	}
+	if p, ok := k.(*rsa.PublicKey); ok {
+		return (*PublicKey)(p), nil
+	}
+	err = fmt.Errorf("Invalid type %s", reflect.TypeOf(k).String())
+	slog.Debugf("Error %v", err)
+	return nil, err
+}
+
+var _ msgpack.CustomEncoder = (*PrivateKey)(nil)
+var _ msgpack.CustomDecoder = (*PrivateKey)(nil)
+
+// EncodeMsgpack func
+func (s *PrivateKey) EncodeMsgpack(enc *msgpack.Encoder) error {
+	return enc.Encode(s.Raw())
+}
+
+// DecodeMsgpack func
+func (s *PrivateKey) DecodeMsgpack(dec *msgpack.Decoder) error {
+	var raw []byte
+	err := dec.Decode(&raw)
+	if err != nil {
+		slog.Warnf("PrivateKey.DecodeMsgpack decode str %v", err)
+		return err
+	}
+	sk, err := x509.ParsePKCS1PrivateKey(raw)
+	if err != nil {
+		slog.Warnf("PrivateKey.DecodeMsgpack parse pkcs key %v", err)
+		return err
+	}
+	s.PublicKey = sk.PublicKey
+	s.D = sk.D
+	s.Primes = sk.Primes
+	s.Precomputed = sk.Precomputed
+	return nil
+}
+
+// Decrypt func
+func (s *PrivateKey) Decrypt(crypt []byte) (plain []byte, err error) {
+	for {
+		if len(crypt) <= decryptBlockSize {
+			bb, err := rsa.DecryptOAEP(sha256.New(), rand.Reader, (*rsa.PrivateKey)(s), crypt, nil)
+			if err != nil {
+				return nil, err
+			}
+			return append(plain, bb...), err
+		}
+		bb, err := rsa.DecryptOAEP(sha256.New(), rand.Reader, (*rsa.PrivateKey)(s), crypt[:decryptBlockSize], nil)
+		if err != nil {
+			return nil, err
+		}
+		plain = append(plain, bb...)
+		crypt = crypt[decryptBlockSize:]
+	}
+}
+
+// MarshalJSON func
+func (s *PrivateKey) MarshalJSON() ([]byte, error) {
+	return []byte("\"" + base64.RawURLEncoding.EncodeToString(s.Raw()) + "\""), nil
+}
+
+// UnmarshalJSON func
+func (s *PrivateKey) UnmarshalJSON(b []byte) error {
+	if b[0] != '"' && b[len(b)-1] != '"' {
+		return fmt.Errorf("Invalid key")
+	}
+	skey := strings.Replace(string(b[1:len(b)-1]), "\\n", "", -1)
+	bb, err := base64.RawURLEncoding.DecodeString(skey)
+	if err != nil {
+		return fmt.Errorf("Error parse privateKey %v [%s]", err, skey)
+	}
+	k, err := x509.ParsePKCS1PrivateKey(bb)
+	if err != nil {
+		return fmt.Errorf("Error parse privateKey %v [%s]", err, string(bb))
+	}
+	s.D = k.D
+	s.E = k.E
+	s.N = k.N
+	s.Primes = k.Primes
+	return ((*rsa.PrivateKey)(s)).Validate()
+}
+
+func (s *PrivateKey) String() string {
+	bb := x509.MarshalPKCS1PrivateKey((*rsa.PrivateKey)(s))
+	return base64.RawURLEncoding.EncodeToString(bb)
+}
+
+// Public func
+func (s *PrivateKey) Public() *PublicKey {
+	rp := (*rsa.PrivateKey)(s).PublicKey
+	return (*PublicKey)(&rp)
+}
+
+// EncryptKey func
+func (s *PrivateKey) EncryptKey(key *PublicKey) EncryptedPrivateKey {
+	bb, err := key.Encrypt(s.Raw())
+	if err != nil {
+		panic(err)
+	}
+	return (EncryptedPrivateKey)(bb)
+}
+
+// Raw func
+func (s *PrivateKey) Raw() []byte {
+	return x509.MarshalPKCS1PrivateKey((*rsa.PrivateKey)(s))
+}
+
+// Equal func
+func (s *PrivateKey) Equal(key *PrivateKey) bool {
+	if key == nil {
+		return s == nil
+	}
+	k1 := (*rsa.PrivateKey)(s)
+	k2 := (*rsa.PrivateKey)(key)
+	return k1.E == k2.E && k1.D.Cmp(k2.D) == 0 && k1.N.Cmp(k2.N) == 0
+}
+
+var _ msgpack.CustomEncoder = (*PublicKey)(nil)
+var _ msgpack.CustomDecoder = (*PublicKey)(nil)
+
+// EncodeMsgpack func
+func (s *PublicKey) EncodeMsgpack(enc *msgpack.Encoder) error {
+	return enc.Encode(s.Raw())
+}
+
+// DecodeMsgpack func
+func (s *PublicKey) DecodeMsgpack(dec *msgpack.Decoder) error {
+	var raw []byte
+	err := dec.Decode(&raw)
+	if err != nil {
+		return err
+	}
+	sko, err := x509.ParsePKIXPublicKey(raw)
+	if err != nil {
+		return err
+	}
+	if sk, ok := sko.(*rsa.PublicKey); ok {
+		s.N = sk.N
+		s.E = sk.E
+		return nil
+	}
+	return fmt.Errorf("Unkown type %s", reflect.TypeOf(sko))
+}
+
+// Encrypt func
+func (s *PublicKey) Encrypt(data []byte) (crypt []byte, err error) {
+	for {
+		if len(data) <= encryptBlockSize {
+			bb, err := rsa.EncryptOAEP(sha256.New(), rand.Reader, (*rsa.PublicKey)(s), data, nil)
+			if err != nil {
+				return nil, err
+			}
+			return append(crypt, bb...), err
+		}
+		bb, err := rsa.EncryptOAEP(sha256.New(), rand.Reader, (*rsa.PublicKey)(s), data[:encryptBlockSize], nil)
+		if err != nil {
+			return nil, err
+		}
+		crypt = append(crypt, bb...)
+		data = data[encryptBlockSize:]
+	}
+}
+
+// MarshalJSON func
+func (s *PublicKey) MarshalJSON() ([]byte, error) {
+	return []byte("\"" + base64.RawURLEncoding.EncodeToString(s.Raw()) + "\""), nil
+}
+
+// UnmarshalJSON func
+func (s *PublicKey) UnmarshalJSON(b []byte) error {
+	if b[0] != '"' && b[len(b)-1] != '"' {
+		return fmt.Errorf("Invalid key")
+	}
+	skey := strings.Replace(string(b[1:len(b)-1]), "\\n", "", -1)
+	bb, err := base64.RawURLEncoding.DecodeString(skey)
+	if err != nil {
+		return fmt.Errorf("Error parse privateKey %v [%s]", err, skey)
+	}
+	k, err := x509.ParsePKIXPublicKey(bb)
+	if err != nil {
+		return fmt.Errorf("Error parse privateKey %v [%s]", err, string(bb))
+	}
+	if pk, ok := k.(*rsa.PublicKey); ok {
+		s.E = pk.E
+		s.N = pk.N
+		return nil
+	}
+	return fmt.Errorf("Invalid type %s", reflect.TypeOf(k))
+}
+
+func (s *PublicKey) String() string {
+	return base64.RawURLEncoding.EncodeToString(s.Raw())
+}
+
+// Raw func
+func (s *PublicKey) Raw() []byte {
+	bb, err := x509.MarshalPKIXPublicKey((*rsa.PublicKey)(s))
+	if err != nil {
+		panic(err)
+	}
+	return bb
+}
+
+// Equal func
+func (s *PublicKey) Equal(key *PublicKey) bool {
+	if key == nil {
+		return s == nil
+	}
+	k1 := (*rsa.PublicKey)(s)
+	k2 := (*rsa.PublicKey)(key)
+	return k1.E == k2.E && k1.N.Cmp(k2.N) == 0
+}

+ 108 - 0
signer/signature.go

@@ -0,0 +1,108 @@
+package signer
+
+import (
+	"crypto"
+	"crypto/ecdsa"
+	"crypto/rand"
+	"crypto/rsa"
+	"encoding/base64"
+	"encoding/binary"
+	"encrypter"
+	"hash"
+	"time"
+
+	msgpack "gopkg.in/vmihailenco/msgpack.v2"
+)
+
+// PrivateKey type
+type PrivateKey ecdsa.PrivateKey
+
+// PublicKey type
+type PublicKey ecdsa.PublicKey
+
+// Signature type
+type Signature []byte
+
+const sha256 = crypto.SHA256
+
+const ivSize = 8
+
+// Signer struct
+type Signer struct {
+	hasher hash.Hash
+}
+
+// New func
+func New() *Signer {
+	return &Signer{hasher: sha256.New()}
+}
+
+// Write func
+func (s *Signer) Write(data []byte) {
+	s.hasher.Write(data)
+}
+
+// WriteTime func
+func (s *Signer) WriteTime(data *time.Time) {
+	b := make([]byte, 8)
+	binary.BigEndian.PutUint64(b, uint64(data.Unix()))
+	s.hasher.Write(b)
+}
+
+// WritePack func
+func (s *Signer) WritePack(data interface{}) {
+	raw, err := msgpack.Marshal(data)
+	if err != nil {
+		panic(err)
+	}
+	s.hasher.Write(raw)
+}
+
+// Reset func
+func (s *Signer) Reset() {
+	s.hasher.Reset()
+}
+
+// Sign func
+func (s *Signer) Sign(key *encrypter.PrivateKey) Signature {
+	sign, err := rsa.SignPKCS1v15(rand.Reader, (*rsa.PrivateKey)(key), sha256, s.hasher.Sum(nil))
+	if err != nil {
+		panic(err)
+	}
+	s.hasher.Reset()
+	return (Signature)(sign)
+}
+
+// Verify func
+func (s *Signer) Verify(key *encrypter.PublicKey, signature Signature) error {
+	err := rsa.VerifyPKCS1v15((*rsa.PublicKey)(key), sha256, s.hasher.Sum(nil), signature)
+	s.hasher.Reset()
+	return err
+}
+
+// SignWithIV func
+func (s *Signer) SignWithIV(key *encrypter.PrivateKey) (Signature, error) {
+	iv := make([]byte, ivSize)
+	_, err := rand.Read(iv)
+	if err != nil {
+		return nil, err
+	}
+	s.hasher.Write(iv)
+	sign, err := rsa.SignPKCS1v15(rand.Reader, (*rsa.PrivateKey)(key), sha256, s.hasher.Sum(nil))
+	s.hasher.Reset()
+	return (Signature)(append(iv, sign...)), err
+}
+
+// VerifyWithIV func
+func (s *Signer) VerifyWithIV(key *encrypter.PublicKey, signature Signature) error {
+	iv := signature[:ivSize]
+	s.hasher.Write(iv)
+	err := rsa.VerifyPKCS1v15((*rsa.PublicKey)(key), sha256, s.hasher.Sum(nil), signature[ivSize:])
+	s.hasher.Reset()
+	return err
+}
+
+// MarshalJSON func
+func (s *Signature) MarshalJSON() ([]byte, error) {
+	return []byte("\"" + base64.RawURLEncoding.EncodeToString(([]byte)(*s)) + "\""), nil
+}

+ 83 - 0
slog/formatter.go

@@ -0,0 +1,83 @@
+package slog
+
+import (
+	"bytes"
+	"fmt"
+
+	"github.com/sirupsen/logrus"
+)
+
+const (
+	nocolor = 0
+	red     = 31
+	green   = 32
+	yellow  = 33
+	blue    = 34
+	gray    = 39
+)
+
+var (
+	formatParams = map[logrus.Level]formatParam{
+		logrus.DebugLevel: formatParam{
+			color:     blue,
+			levelText: "DEBUG",
+		},
+		logrus.InfoLevel: formatParam{
+			color:     green,
+			levelText: "INFO",
+		},
+		logrus.WarnLevel: formatParam{
+			color:     yellow,
+			levelText: "WARN",
+		},
+		logrus.ErrorLevel: formatParam{
+			color:     red,
+			levelText: "ERROR",
+		},
+	}
+)
+
+type (
+	formatter struct {
+		logrus.TextFormatter
+	}
+
+	formatParam struct {
+		color     int
+		levelText string
+	}
+)
+
+func newFormatter(color bool) *formatter {
+	return &formatter{
+		logrus.TextFormatter{
+			ForceColors:   color,
+			DisableColors: !color,
+		},
+	}
+}
+
+/**************************
+ formatter function
+**************************/
+func (f *formatter) Format(entry *logrus.Entry) ([]byte, error) {
+	formatParams := formatParams[entry.Level]
+	b := &bytes.Buffer{}
+	if f.ForceColors && !f.DisableColors {
+		fmt.Fprintf(b,
+			"\x1b[%dm[%-5s]\x1b[0m %s",
+			formatParams.color,
+			formatParams.levelText,
+			entry.Message,
+		)
+	} else {
+		fmt.Fprintf(b,
+			"[%-5s] %s",
+			formatParams.levelText,
+			entry.Message,
+		)
+	}
+
+	b.WriteByte('\n')
+	return b.Bytes(), nil
+}

+ 177 - 0
slog/slog.go

@@ -0,0 +1,177 @@
+package slog
+
+import (
+	"os"
+	"strings"
+
+	logrus_stack "github.com/Gurpartap/logrus-stack"
+	"github.com/mattn/go-colorable"
+	"github.com/sirupsen/logrus"
+)
+
+type logger struct {
+	*logrus.Logger
+}
+
+var rootLogger *logger
+
+func init() {
+	rootLogger = newRootLogger()
+	logrus.AddHook(logrus_stack.NewHook(nil, []logrus.Level{logrus.PanicLevel, logrus.FatalLevel, logrus.ErrorLevel, logrus.WarnLevel}))
+	logrus.SetLevel(logrus.InfoLevel)
+}
+
+func newRootLogger() *logger {
+	switch strings.ToLower(os.Getenv("LOG_LEVEL")) {
+	case "panic":
+		logrus.SetLevel(logrus.PanicLevel)
+	case "fatal":
+		logrus.SetLevel(logrus.FatalLevel)
+	case "error":
+		logrus.SetLevel(logrus.ErrorLevel)
+	case "warn", "warning":
+		logrus.SetLevel(logrus.WarnLevel)
+	case "info":
+		logrus.SetLevel(logrus.InfoLevel)
+	case "debug":
+		logrus.SetLevel(logrus.DebugLevel)
+	default:
+		logrus.SetLevel(logrus.InfoLevel)
+	}
+	logrus.SetOutput(colorable.NewColorableStdout())
+	logrus.SetFormatter(newFormatter(true))
+	return &logger{logrus.StandardLogger()}
+}
+
+// SetLevelToDebug func
+func SetLevelToDebug() {
+	logrus.SetLevel(logrus.DebugLevel)
+}
+
+// SetLevelToInfo func
+func SetLevelToInfo() {
+	logrus.SetLevel(logrus.InfoLevel)
+}
+
+// SetLevelToWarn func
+func SetLevelToWarn() {
+	logrus.SetLevel(logrus.WarnLevel)
+}
+
+// Debugf func
+func Debugf(format string, args ...interface{}) {
+	if rootLogger.Level >= logrus.DebugLevel {
+		if len(args) == 1 {
+			if fx, ok := args[0].(func() interface{}); ok {
+				rootLogger.Debugf(format, fx())
+				return
+			}
+			if fx, ok := args[0].(func() []interface{}); ok {
+				rootLogger.Debugf(format, fx()...)
+				return
+			}
+		}
+		rootLogger.Debugf(format, args...)
+	}
+}
+
+// Infof func
+func Infof(format string, args ...interface{}) {
+	if rootLogger.Level >= logrus.InfoLevel {
+		if len(args) == 1 {
+			if fx, ok := args[0].(func() interface{}); ok {
+				rootLogger.Infof(format, fx())
+				return
+			}
+			if fx, ok := args[0].(func() []interface{}); ok {
+				rootLogger.Infof(format, fx()...)
+				return
+			}
+		}
+		rootLogger.Infof(format, args...)
+	}
+}
+
+// Warnf func
+func Warnf(format string, args ...interface{}) {
+	if len(args) == 1 {
+		if fx, ok := args[0].(func() interface{}); ok {
+			rootLogger.Warnf(format, fx())
+			return
+		}
+		if fx, ok := args[0].(func() []interface{}); ok {
+			rootLogger.Warnf(format, fx()...)
+			return
+		}
+	}
+	rootLogger.Warnf(format, args...)
+}
+
+// Errorf func
+func Errorf(format string, args ...interface{}) {
+	if len(args) == 1 {
+		if fx, ok := args[0].(func() interface{}); ok {
+			rootLogger.Errorf(format, fx())
+			return
+		}
+		if fx, ok := args[0].(func() []interface{}); ok {
+			rootLogger.Errorf(format, fx()...)
+			return
+		}
+	}
+	rootLogger.Errorf(format, args...)
+}
+
+// Panicf func
+func Panicf(format string, args ...interface{}) {
+	if len(args) == 1 {
+		if fx, ok := args[0].(func() interface{}); ok {
+			rootLogger.Panicf(format, fx())
+			return
+		}
+		if fx, ok := args[0].(func() []interface{}); ok {
+			rootLogger.Panicf(format, fx()...)
+			return
+		}
+	}
+	rootLogger.Panicf(format, args...)
+}
+
+// Debug func
+func Debug(args ...interface{}) {
+	if rootLogger.Level >= logrus.DebugLevel {
+		if len(args) == 1 {
+			if fx, ok := args[0].(func() interface{}); ok {
+				rootLogger.Debug(fx())
+				return
+			}
+			if fx, ok := args[0].(func() []interface{}); ok {
+				rootLogger.Debug(fx()...)
+				return
+			}
+		}
+		rootLogger.Debug(args...)
+	}
+}
+
+// Info func
+func Info(args ...interface{}) {
+	if rootLogger.Level >= logrus.InfoLevel {
+		rootLogger.Info(args...)
+	}
+}
+
+// Warn func
+func Warn(args ...interface{}) {
+	rootLogger.Warn(args...)
+}
+
+// Error func
+func Error(args ...interface{}) {
+	rootLogger.Error(args...)
+}
+
+// Panic func
+func Panic(args ...interface{}) {
+	rootLogger.Panic(args...)
+}

+ 8 - 0
util/util.go

@@ -0,0 +1,8 @@
+package util
+
+import "fmt"
+
+// Todo func
+func Todo(msg string) error {
+	return fmt.Errorf("TODO %s", msg)
+}