Golang标准库——crypto(1)

DevilRoshan · · 1319 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

  • aes
  • cipher
  • des
  • dsa
  • ecdsa
  • elliptic

crypto

crypto包搜集了常用的密码(算法)常量。

type PublicKey

type PublicKey interface{}

代表一个使用未指定算法的公钥。

type PrivateKey

type PrivateKey interface{}

代表一个使用未指定算法的私钥。

type Hash

type Hash uint

Hash用来识别/标识另一个包里实现的加密函数。

const (
    MD4       Hash = 1 + iota // 导入code.google.com/p/go.crypto/md4
    MD5                       // 导入crypto/md5
    SHA1                      // 导入crypto/sha1
    SHA224                    // 导入crypto/sha256
    SHA256                    // 导入crypto/sha256
    SHA384                    // 导入crypto/sha512
    SHA512                    // 导入crypto/sha512
    MD5SHA1                   // 未实现;MD5+SHA1用于TLS RSA
    RIPEMD160                 // 导入code.google.com/p/go.crypto/ripemd160
)

func (Hash) Available

func (h Hash) Available() bool

报告是否有hash函数注册到该标识值。

func (Hash) Size

func (h Hash) Size() int

返回给定hash函数返回值的字节长度。

func (Hash) New

func (h Hash) New() hash.Hash

创建一个使用给定hash函数的hash.Hash接口,如果该标识值未注册hash函数,将会panic。

func RegisterHash

func RegisterHash(h Hash, f func() hash.Hash)

注册一个返回给定hash接口实例的函数,并指定其标识值,该函数应在实现hash接口的包的init函数中调用。

aes

aes包实现了AES加密算法,参见U.S. Federal Information Processing Standards Publication 197。

Constants

const BlockSize = 16

AES字节块大小。

type KeySizeError

type KeySizeError int

func (KeySizeError) Error

func (k KeySizeError) Error() string

func NewCipher

func NewCipher(key []byte) (cipher.Block, error)

创建一个cipher.Block接口。参数key为密钥,长度只能是16、24、32字节,用以选择AES-128、AES-192、AES-256。

// 填充
func padding(src []byte, blockSize int) []byte {
   padNum := blockSize - len(src) % blockSize
   pad := bytes.Repeat([]byte{byte(padNum)}, padNum)
   fmt.Println(string(pad))
   return append(src, pad...)
}

// 去掉填充
func unpadding(src []byte) []byte {
   n := len(src)
   unPadNum := int(src[n-1])
   return src[:n-unPadNum]
}

// 加密
func encryptAES(src []byte, key []byte) ([]byte, error) {
   block, err := aes.NewCipher(key)

   if err != nil {
      return nil, err
   }
   src = padding(src, block.BlockSize())
   fmt.Println(len(src))
   blockMode := cipher.NewCBCEncrypter(block, key)
   blockMode.CryptBlocks(src, src)
   return src, nil
}

// 解密
func decryptAES(src []byte, key []byte) ([]byte, error) {
   block, err := aes.NewCipher(key)
   if err != nil {
      return nil, err
   }
   blockMode := cipher.NewCBCDecrypter(block, key)
   blockMode.CryptBlocks(src, src)
   src = unpadding(src)
   return src, nil
}

cipher

cipher包实现了多个标准的用于包装底层块加密算法的加密算法实现。

type Block

type Block interface {
    // 返回加密字节块的大小
    BlockSize() int
    // 加密src的第一块数据并写入dst,src和dst可指向同一内存地址
    Encrypt(dst, src []byte)
    // 解密src的第一块数据并写入dst,src和dst可指向同一内存地址
    Decrypt(dst, src []byte)
}

Block接口代表一个使用特定密钥的底层块加/解密器。它提供了加密和解密独立数据块的能力。

type BlockMode

type BlockMode interface {
    // 返回加密字节块的大小
    BlockSize() int
    // 加密或解密连续的数据块,src的尺寸必须是块大小的整数倍,src和dst可指向同一内存地址
    CryptBlocks(dst, src []byte)
}

BlockMode接口代表一个工作在块模式(如CBC、ECB等)的加/解密器。

func NewCBCEncrypter

func NewCBCEncrypter(b Block, iv []byte) BlockMode

返回一个密码分组链接模式的、底层用b加密的BlockMode接口,初始向量iv的长度必须等于b的块尺寸。

func NewCBCDecrypter

func NewCBCDecrypter(b Block, iv []byte) BlockMode

返回一个密码分组链接模式的、底层用b解密的BlockMode接口,初始向量iv必须和加密时使用的iv相同。

type Stream

type Stream interface {
    // 从加密器的key流和src中依次取出字节二者xor后写入dst,src和dst可指向同一内存地址
    XORKeyStream(dst, src []byte)
}

Stream接口代表一个流模式的加/解密器。

func NewCFBEncrypter

func NewCFBEncrypter(block Block, iv []byte) Stream

返回一个密码反馈模式的、底层用block加密的Stream接口,初始向量iv的长度必须等于block的块尺寸。

func NewCFBDecrypter

func NewCFBDecrypter(block Block, iv []byte) Stream

返回一个密码反馈模式的、底层用block解密的Stream接口,初始向量iv必须和加密时使用的iv相同。

func NewOFB

func NewOFB(b Block, iv []byte) Stream

返回一个输出反馈模式的、底层采用b生成key流的Stream接口,初始向量iv的长度必须等于b的块尺寸。

func NewCTR

func NewCTR(block Block, iv []byte) Stream

返回一个计数器模式的、底层采用block生成key流的Stream接口,初始向量iv的长度必须等于block的块尺寸。

type StreamReader

type StreamReader struct {
    S   Stream
    R   io.Reader
}

将一个Stream与一个io.Reader接口关联起来,Read方法会调用XORKeyStream方法来处理获取的所有切片。

func (StreamReader) Read

func (r StreamReader) Read(dst []byte) (n int, err error)

type StreamWriter

type StreamWriter struct {
    S   Stream
    W   io.Writer
    Err error // unused
}

将一个Stream与一个io.Writer接口关联起来,Write方法会调用XORKeyStream方法来处理提供的所有切片。如果Write方法返回的n小于提供的切片的长度,则表示StreamWriter不同步,必须丢弃。StreamWriter没有内建的缓存,不需要调用Close方法去清空缓存。

func (StreamWriter) Write

func (w StreamWriter) Write(src []byte) (n int, err error)

func (StreamWriter) Close

func (w StreamWriter) Close() error

如果w.W字段实现了io.Closer接口,本方法会调用其Close方法并返回该方法的返回值;否则不做操作返回nil。

type AEAD

type AEAD interface {
    // 返回提供给Seal和Open方法的随机数nonce的字节长度
    NonceSize() int
    // 返回原始文本和加密文本的最大长度差异
    Overhead() int
    // 加密并认证明文,认证附加的data,将结果添加到dst,返回更新后的切片。
    // nonce的长度必须是NonceSize()字节,且对给定的key和时间都是独一无二的。
    // plaintext和dst可以是同一个切片,也可以不同。
    Seal(dst, nonce, plaintext, data []byte) []byte
    // 解密密文并认证,认证附加的data,如果认证成功,将明文添加到dst,返回更新后的切片。
    // nonce的长度必须是NonceSize()字节,nonce和data都必须和加密时使用的相同。
    // ciphertext和dst可以是同一个切片,也可以不同。
    Open(dst, nonce, ciphertext, data []byte) ([]byte, error)
}

AEAD接口是一种提供了使用关联数据进行认证加密的功能的加密模式。

func NewGCM

func NewGCM(cipher Block) (AEAD, error)

函数用迦洛瓦计数器模式包装提供的128位Block接口,并返回AEAD接口。

des

des包实现了DES标准和TDEA算法,参见U.S. Federal Information Processing Standards Publication 46-3。

Constants

const BlockSize = 8

DES字节块的大小。

type KeySizeError

type KeySizeError int

func (KeySizeError) Error

func (k KeySizeError) Error() string

func NewCipher

func NewCipher(key []byte) (cipher.Block, error)

创建并返回一个使用DES算法的cipher.Block接口。

func NewTripleDESCipher

func NewTripleDESCipher(key []byte) (cipher.Block, error)

创建并返回一个使用TDEA算法的cipher.Block接口。

// 填充
func padding(src []byte, blockSize int) []byte {
   padNum := blockSize - len(src) % blockSize
   pad := bytes.Repeat([]byte{byte(padNum)}, padNum)
   fmt.Println(string(pad))
   return append(src, pad...)
}

// 去掉填充
func unpadding(src []byte) []byte {
   n := len(src)
   unPadNum := int(src[n-1])
   return src[:n-unPadNum]
}

// 加密
func encryptDES(src []byte, key []byte) ([]byte, error) {
   block, err := des.NewCipher(key)

   if err != nil {
      return nil, err
   }
   src = padding(src, block.BlockSize())
   blockMode := cipher.NewCBCEncrypter(block, key)
   blockMode.CryptBlocks(src, src)
   return src, nil
}

// 解密
func decryptDES(src []byte, key []byte) ([]byte, error) {
   block, err := des.NewCipher(key)
   if err != nil {
      return nil, err
   }
   blockMode := cipher.NewCBCDecrypter(block, key)
   blockMode.CryptBlocks(src, src)
   src = unpadding(src)
   return src, nil
}

func main() {
   d := []byte("hello world")
   key := []byte("12345678")
   fmt.Println("加密前:", string(d))
   x1, err := encryptDES(d, key)
   if err != nil {
      fmt.Println(err)
   }
   fmt.Println("加密后:", string(x1))
   x2, err := decryptDES(x1, key)
   if err != nil {
      fmt.Println(err)
   }
   fmt.Println("解密后:", string(x2))
}

dsa

dsa包实现FIPS 186-3定义的数字签名算法(Digital Signature Algorithm),即DSA算法

Variables

var ErrInvalidPublicKey = errors.New("crypto/dsa: invalid public key")

非法公钥,FIPS标准的公钥格式是很严格的,但有些实现没这么严格,使用这些实现的公钥时,就会导致这个错误。

type ParameterSizes

type ParameterSizes int

是DSA参数中的质数可以接受的字位长度的枚举,参见FIPS 186-3 section 4.2。

const (
    L1024N160 ParameterSizes = iota
    L2048N224
    L2048N256
    L3072N256
)

type Parameters

type Parameters struct {
    P, Q, G *big.Int
}

Parameters代表密钥的域参数,这些参数可以被一组密钥共享,Q的字位长度必须是8的倍数。

type PublicKey

type PublicKey struct {
    Parameters
    Y   *big.Int
}

PublicKey代表一个DSA公钥。

type PrivateKey

type PrivateKey struct {
    PublicKey
    X   *big.Int
}

PrivateKey代表一个DSA私钥。

func GenerateKey

func GenerateParameters

func GenerateParameters(params *Parameters, rand io.Reader, sizes ParameterSizes) (err error)

GenerateParameters函数随机设置合法的参数到params。即使机器很快,函数也可能会花费很多时间来生成参数。

func GenerateKey(priv *PrivateKey, rand io.Reader) error

GenerateKey生成一对公钥和私钥;priv.PublicKey.Parameters字段必须已经(被GenerateParameters函数)设置了合法的参数。

func Sign

func Sign(rand io.Reader, priv *PrivateKey, hash []byte) (r, s *big.Int, err error)

使用私钥对任意长度的hash值(必须是较大信息的hash结果)进行签名,返回签名结果(一对大整数)。私钥的安全性取决于密码读取器的熵度(随机程度)。

注意根据FIPS 186-3 section 4.6的规定,hash必须被截断到亚组的长度,本函数是不会自己截断的。

func Verify

func Verify(pub *PublicKey, hash []byte, r, s *big.Int) bool

使用公钥认证hash和两个大整数r、s构成的签名,报告签名是否合法。

注意根据FIPS 186-3 section 4.6的规定,hash必须被截断到亚组的长度,本函数是不会自己截断的。

func main() {
   // parameters 是私钥的参数
   var param dsa.Parameters
   // L1024N160是一个枚举,根据L1024N160来决定私钥的长度(L N)
   dsa.GenerateParameters(&param, rand.Reader, dsa.L1024N160)
   // 定义私钥的变量
   var privateKey dsa.PrivateKey
   // 设置私钥的参数
   privateKey.Parameters = param
   // 生成密钥对
   dsa.GenerateKey(&privateKey, rand.Reader)
   // 公钥是存在在私钥中的,从私钥中读取公钥
   publicKey := privateKey.PublicKey
   message := []byte("hello,dsa签名")

   fmt.Println(publicKey)
   fmt.Println(privateKey)

   // 进入签名操作
   r, s, _ := dsa.Sign(rand.Reader, &privateKey, message)

   // 进入验证
   flag := dsa.Verify(&publicKey, message, r, s)
   if flag {
      fmt.Println("数据未被修改")
   } else {
      fmt.Println("数据被修改")
   }
   flag = dsa.Verify(&publicKey, []byte("hello"), r, s)
   if flag {
      fmt.Println("数据未被修改")
   } else {
      fmt.Println("数据被修改")
   }
}

ecdsa

ecdsa包实现了椭圆曲线数字签名算法,参见FIPS 186-3。

type PublicKey

type PublicKey struct {
    elliptic.Curve
    X, Y *big.Int
}

PrivateKey代表一个ECDSA公钥。

type PrivateKey

type PrivateKey struct {
    PublicKey
    D   *big.Int
}

PrivateKey代表一个ECDSA私钥。

func GenerateKey

GenerateKey函数生成一对

func GenerateKey(c elliptic.Curve, rand io.Reader) (priv *PrivateKey, err error)

公钥/私钥。

func Sign

func Sign(rand io.Reader, priv *PrivateKey, hash []byte) (r, s *big.Int, err error)

使用私钥对任意长度的hash值(必须是较大信息的hash结果)进行签名,返回签名结果(一对大整数)。私钥的安全性取决于密码读取器的熵度(随机程度)。

func Verify

func Verify(pub *PublicKey, hash []byte, r, s *big.Int) bool

使用公钥验证hash值和两个大整数r、s构成的签名,并返回签名是否合法。

elliptic

elliptic包实现了几条覆盖素数有限域的标准椭圆曲线。

type Curve

type Curve interface {
    // Params返回椭圆曲线的参数
    Params() *CurveParams
    // IsOnCurve判断一个点是否在椭圆曲线上
    IsOnCurve(x, y *big.Int) bool
    // 返回点(x1,y1)和点(x2,y2)相加的结果
    Add(x1, y1, x2, y2 *big.Int) (x, y *big.Int)
    // 返回2*(x,y),即(x,y)+(x,y)
    Double(x1, y1 *big.Int) (x, y *big.Int)
    // k是一个大端在前格式的数字,返回k*(Bx,By)
    ScalarMult(x1, y1 *big.Int, k []byte) (x, y *big.Int)
    // k是一个大端在前格式的数字,返回k*G,G是本椭圆曲线的基点
    ScalarBaseMult(k []byte) (x, y *big.Int)
}

Curve代表一个短格式的Weierstrass椭圆曲线,其中a=-3。

Weierstrass椭圆曲线的格式:y2 = x3 + a*x + b

func P224

func P224() Curve

返回一个实现了P-224的曲线。(参见FIPS 186-3, section D.2.2)

func P256

func P256() Curve

返回一个实现了P-256的曲线。(参见FIPS 186-3, section D.2.3)

func P384

func P384() Curve

返回一个实现了P-384的曲线。(参见FIPS 186-3, section D.2.4)

func P521

func P521() Curve

返回一个实现了P-512的曲线。(参见FIPS 186-3, section D.2.5)

type CurveParams

type CurveParams struct {
    P       *big.Int // 决定有限域的p的值(必须是素数)
    N       *big.Int // 基点的阶(必须是素数)
    B       *big.Int // 曲线公式的常量(B!=2)
    Gx, Gy  *big.Int // 基点的坐标
    BitSize int      // 决定有限域的p的字位数
}

CurveParams包含一个椭圆曲线的所有参数,也可提供一般的、非常数时间实现的椭圆曲线。

func (*CurveParams) Params

func (curve *CurveParams) Params() *CurveParams

func (*CurveParams) IsOnCurve

func (curve *CurveParams) IsOnCurve(x, y *big.Int) bool

func (*CurveParams) Add

func (curve *CurveParams) Add(x1, y1, x2, y2 *big.Int) (*big.Int, *big.Int)

func (*CurveParams) Double

func (curve *CurveParams) Double(x1, y1 *big.Int) (*big.Int, *big.Int)

func (*CurveParams) ScalarMult

func (curve *CurveParams) ScalarMult(Bx, By *big.Int, k []byte) (*big.Int, *big.Int)

func (*CurveParams) ScalarBaseMult

func (curve *CurveParams) ScalarBaseMult(k []byte) (*big.Int, *big.Int)

func GenerateKey

func GenerateKey(curve Curve, rand io.Reader) (priv []byte, x, y *big.Int, err error)

GenerateKey返回一个公钥/私钥对。priv是私钥,而(x,y)是公钥。密钥对是通过提供的随机数读取器来生成的,该io.Reader接口必须返回随机数据。

func Marshal

func Marshal(curve Curve, x, y *big.Int) []byte

Marshal将一个点编码为ANSI X9.62指定的格式。

func Unmarshal

func Unmarshal(curve Curve, data []byte) (x, y *big.Int)

将一个Marshal编码后的点还原;如果出错,x会被设为nil。


有疑问加站长微信联系(非本文作者)

本文来自:简书

感谢作者:DevilRoshan

查看原文:Golang标准库——crypto(1)

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

1319 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传