golang blowfish ecb pkcs5 加解密

package main

import (
    "bytes"
    "crypto/cipher"
    "encoding/base64"
    "errors"
    "fmt"
    "strconv"

    "golang.org/x/crypto/blowfish"
)

func main() {
    key := "PPpn7ugdcTa4DTUdqSkxSeR7gTsv93Q576ug8QMdeLbVFPte"
    price := "29.20"
    enc, err := BlowfishECBEncrypt(price, key)
    if err != nil {
        fmt.Println("-------err: ", err)
    }
    encodeStr := base64.URLEncoding.EncodeToString(enc)
    fmt.Println("encode=", encodeStr)

    enc, err = base64.URLEncoding.DecodeString(encodeStr)
    if err != nil {
        fmt.Println("-------err: ", err)
    }

    price2, err := BlowfishECBDecrypt(enc, []byte(key))
    if err != nil {
        fmt.Println("--------err decode=", err)
    }

    fmt.Println("decode=", string(price2))
    price1, err := strconv.ParseFloat(string(price2), 64)
    if err != nil {
        fmt.Println("parse float is failed, err:", err)
    }
    fmt.Println("------------price1=", price1)
}

func BlowfishECBEncrypt(src, key string) ([]byte, error) {
    block, err := blowfish.NewCipher([]byte(key))
    if err != nil {
        return nil, err
    }
    if src == "" {
        return nil, errors.New("plain content empty")
    }
    ecb := NewECBEncrypter(block)
    content := []byte(src)
    content = PKCS5Padding(content, block.BlockSize())
    crypted := make([]byte, len(content))
    ecb.CryptBlocks(crypted, content)
    return crypted, nil
}

func BlowfishECBDecrypt(crypted, key []byte) ([]byte, error) {
    block, err := blowfish.NewCipher([]byte(key))
    if err != nil {
        return nil, err
    }
    blockMode := NewECBDecrypter(block)
    origData := make([]byte, len(crypted))
    blockMode.CryptBlocks(origData, crypted)
    origData = PKCS5UnPadding(origData)
    return origData, nil
}

type ECB struct {
    b         cipher.Block
    blockSize int
}

func NewECB(b cipher.Block) *ECB {
    return &ECB{
        b:         b,
        blockSize: b.BlockSize(),
    }
}

type ECBEncrypter ECB

// NewECBEncrypter returns a BlockMode which encrypts in electronic code book
// mode, using the given Block.
func NewECBEncrypter(b cipher.Block) cipher.BlockMode {
    return (*ECBEncrypter)(NewECB(b))
}
func (x *ECBEncrypter) BlockSize() int { return x.blockSize }
func (x *ECBEncrypter) CryptBlocks(dst, src []byte) {
    if len(src)%x.blockSize != 0 {
        panic("crypto/cipher: input not full blocks")
    }
    if len(dst) < len(src) {
        panic("crypto/cipher: output smaller than input")
    }
    for len(src) > 0 {
        x.b.Encrypt(dst, src[:x.blockSize])
        src = src[x.blockSize:]
        dst = dst[x.blockSize:]
    }
}

type ECBDecrypter ECB

// NewECBDecrypter returns a BlockMode which decrypts in electronic code book
// mode, using the given Block.
func NewECBDecrypter(b cipher.Block) cipher.BlockMode {
    return (*ECBDecrypter)(NewECB(b))
}
func (x *ECBDecrypter) BlockSize() int {
    return x.blockSize
}
func (x *ECBDecrypter) CryptBlocks(dst, src []byte) {
    if len(src)%x.blockSize != 0 {
        panic("crypto/cipher: input not full blocks")
    }
    if len(dst) < len(src) {
        panic("crypto/cipher: output smaller than input")
    }
    for len(src) > 0 {
        x.b.Decrypt(dst, src[:x.blockSize])
        src = src[x.blockSize:]
        dst = dst[x.blockSize:]
    }
}

// PKCS5Padding _
func PKCS5Padding(ciphertext []byte, blockSize int) []byte {
    padding := blockSize - len(ciphertext)%blockSize
    padtext := bytes.Repeat([]byte{byte(padding)}, padding)
    return append(ciphertext, padtext...)
}

// PKCS5UnPadding _
func PKCS5UnPadding(origData []byte) []byte {
    length := len(origData)
    // 去掉最后一个字节 unpadding 次
    unpadding := int(origData[length-1])
    return origData[:(length - unpadding)]
}

 

posted @ 2019-05-13 09:51  追逐~~~  阅读(1550)  评论(0编辑  收藏  举报