zoukankan      html  css  js  c++  java
  • IBM openblockchain学习(四)--crypto源码分析

    crypto是blockchain中加密技术功能的实现,其中包括了椭圆曲线加密和SHA256等加密算法等,接下来将对其核心部分进行解析。

    elliptic

    返回加密层中使用的默认椭圆曲线

    func GetDefaultCurve() elliptic.Curve {
        return defaultCurve
    }
    

    hash

    返回加密层中使用的默认哈希值

    func GetDefaultHash() func() hash.Hash {
        return defaultHash
    }

    init

    在给定的安全级别内初始化密码层

    func InitSecurityLevel(level int) (err error) {
        initOnce.Do(func() {
            switch level {
            case 256:
                defaultCurve = elliptic.P256()
                defaultHash = sha3.New256
            case 384:
                defaultCurve = elliptic.P384()
                defaultHash = sha3.New384
            default:
                err = fmt.Errorf("Security level not supported [%d]", level)
            }
        })
    
        return
    }

    generic

    generic位于ecies包下

    engine

    aesEncrypt

    ase加密

    func aesEncrypt(key, plain []byte) ([]byte, error) {
        block, err := aes.NewCipher(key)
        if err != nil {
            return nil, err
        }
    
        text := make([]byte, aes.BlockSize+len(plain))
        iv := text[:aes.BlockSize]
        if _, err := io.ReadFull(rand.Reader, iv); err != nil {
            return nil, err
        }
    
        cfb := cipher.NewCFBEncrypter(block, iv)
        cfb.XORKeyStream(text[aes.BlockSize:], plain)
    
        return text, nil
    }

    aesDecrypt

    aes解密

    func aesDecrypt(key, text []byte) ([]byte, error) {
        block, err := aes.NewCipher(key)
        if err != nil {
            return nil, err
        }
    
        if len(text) < aes.BlockSize {
            return nil, errors.New("cipher text too short")
        }
    
        cfb := cipher.NewCFBDecrypter(block, text[:aes.BlockSize])
        plain := make([]byte, len(text)-aes.BlockSize)
        cfb.XORKeyStream(plain, text[aes.BlockSize:])
    
        return plain, nil
    }
    

    eciesGenerateKey

    ECIES生成密钥

    func eciesGenerateKey(rand io.Reader, curve elliptic.Curve, params *Params) (*ecdsa.PrivateKey, error) {
        return ecdsa.GenerateKey(curve, rand)
    }
    

    eciesEncrypt

    func eciesEncrypt(rand io.Reader, pub *ecdsa.PublicKey, s1, s2 []byte, plain []byte) ([]byte, error) {
        params := pub.Curve.Params()
    
        //选择带有椭圆曲线域参数相关的临时椭圆曲线密钥对
        priv, Rx, Ry, err := elliptic.GenerateKey(pub.Curve, rand)
        //fmt.Printf("Rx %s
    ", utils.EncodeBase64(Rx.Bytes()))
        //fmt.Printf("Ry %s
    ", utils.EncodeBase64(Ry.Bytes()))
    
        // 转换 R=(Rx,Ry) 为R字节串
        // 这是未压缩的
        Rb := elliptic.Marshal(pub.Curve, Rx, Ry)
    
        // 从暂时的私钥k得出一个公钥元素z,并且将字节串z转化为Z
        z, _ := params.ScalarMult(pub.X, pub.Y, priv)
        Z := z.Bytes()
        //fmt.Printf("Z %s
    ", utils.EncodeBase64(Z))
    
        //借助Z中生成长度为ecnKeyLen+macKeyLen的公钥数据K
    
        // ans s1
        kE := make([]byte, 32)
        kM := make([]byte, 32)
        hkdf := hkdf.New(conf.GetDefaultHash(), Z, s1, nil)
        _, err = hkdf.Read(kE)
        if err != nil {
            return nil, err
        }
        _, err = hkdf.Read(kM)
        if err != nil {
            return nil, err
        }
    
        //使用对称加密方案的加密运算加密m在EK中的密文EM
        EM, err := aesEncrypt(kE, plain)
    
        //使用MAC方案的标签操作来计算EM上的标签D||S2
        mac := hmac.New(conf.GetDefaultHash(), kM)
        mac.Write(EM)
        if len(s2) > 0 {
            mac.Write(s2)
        }
        D := mac.Sum(nil)
    
        // Output R,EM,D
        ciphertext := make([]byte, len(Rb)+len(EM)+len(D))
        //fmt.Printf("Rb %s
    ", utils.EncodeBase64(Rb))
        //fmt.Printf("EM %s
    ", utils.EncodeBase64(EM))
        //fmt.Printf("D %s
    ", utils.EncodeBase64(D))
        copy(ciphertext, Rb)
        copy(ciphertext[len(Rb):], EM)
        copy(ciphertext[len(Rb)+len(EM):], D)
    
        return ciphertext, nil
    }

    eciesDecrypt

    func eciesDecrypt(priv *ecdsa.PrivateKey, s1, s2 []byte, ciphertext []byte) ([]byte, error) {
        params := priv.Curve.Params()
    
        var (
            rLen   int
            hLen   int = conf.GetDefaultHash()().Size()
            mStart int
            mEnd   int
        )
    
        //fmt.Printf("Decrypt
    ")
        switch ciphertext[0] {
        case 2, 3:
            rLen = ((priv.PublicKey.Curve.Params().BitSize + 7) / 8) + 1
            if len(ciphertext) < (rLen + hLen + 1) {
                return nil, errors.New("Invalid ciphertext")
            }
            break
        case 4:
            rLen = 2*((priv.PublicKey.Curve.Params().BitSize+7)/8) + 1
            if len(ciphertext) < (rLen + hLen + 1) {
                return nil, errors.New("Invalid ciphertext")
            }
            break
    
        default:
            return nil, errors.New("Invalid ciphertext")
        }
    
        mStart = rLen
        mEnd = len(ciphertext) - hLen
        //fmt.Printf("Rb %s
    ", utils.EncodeBase64(ciphertext[:rLen]))
    
        Rx, Ry := elliptic.Unmarshal(priv.Curve, ciphertext[:rLen])
        if Rx == nil {
            return nil, errors.New("Invalid ephemeral PK")
        }
        if !priv.Curve.IsOnCurve(Rx, Ry) {
            return nil, errors.New("Invalid point on curve")
        }
        //fmt.Printf("Rx %s
    ", utils.EncodeBase64(Rx.Bytes()))
        //fmt.Printf("Ry %s
    ", utils.EncodeBase64(Ry.Bytes()))
    
        // 从暂时的私钥k得出一个公钥z,并转换z到字节串Z
        z, _ := params.ScalarMult(Rx, Ry, priv.D.Bytes())
        Z := z.Bytes()
        //fmt.Printf("Z %s
    ", utils.EncodeBase64(Z))
    
    
        kE := make([]byte, 32)
        kM := make([]byte, 32)
        hkdf := hkdf.New(conf.GetDefaultHash(), Z, s1, nil)
        _, err := hkdf.Read(kE)
        if err != nil {
            return nil, err
        }
        _, err = hkdf.Read(kM)
        if err != nil {
            return nil, err
        }
    
        // 使用MAC方案的标签操作来计算EM上的标签,再对比D||S2
        mac := hmac.New(conf.GetDefaultHash(), kM)
        mac.Write(ciphertext[mStart:mEnd])
        if len(s2) > 0 {
            mac.Write(s2)
        }
        D := mac.Sum(nil)
    
        //fmt.Printf("EM %s
    ", utils.EncodeBase64(ciphertext[mStart:mEnd]))
        //fmt.Printf("D' %s
    ", utils.EncodeBase64(D))
        //fmt.Printf("D %s
    ", utils.EncodeBase64(ciphertext[mEnd:]))
        if subtle.ConstantTimeCompare(ciphertext[mEnd:], D) != 1 {
            return nil, errors.New("Tag check failed")
        }
    
        // 使用对称加密方案的解密操作使用明文EK解密EM
    
        plaintext, err := aesDecrypt(kE, ciphertext[mStart:mEnd])
    
        return plaintext, err
    }
    

    es

    func (es *encryptionSchemeImpl) Init(params ecies.AsymmetricCipherParameters) error {
        if params == nil {
            return ecies.ErrInvalidKeyParameter
        }
        es.isForEncryption = params.IsPublic()
        es.params = params
    
        if es.isForEncryption {
            switch pk := params.(type) {
            case *publicKeyImpl:
                es.pub = pk
            default:
                return ecies.ErrInvalidKeyParameter
            }
        } else {
            switch sk := params.(type) {
            case *secretKeyImpl:
                es.priv = sk
            default:
                return ecies.ErrInvalidKeyParameter
            }
        }
    
        return nil
    }
    
    func (es *encryptionSchemeImpl) Process(msg []byte) ([]byte, error) {
        if es.isForEncryption {
            // 加密
            return eciesEncrypt(es.params.GetRand(), es.pub.pub, nil, nil, msg)
        } else {
            // 解密
            return eciesDecrypt(es.priv.priv, nil, nil, msg)
        }
    
        return nil, nil
    }

    kg

    生成密钥

    func (kg *keyGeneratorImpl) GenerateKey() (ecies.PrivateKey, error) {
    
        privKey, err := eciesGenerateKey(
            kg.params.rand,
            kg.params.curve,
            kg.params.params,
        )
        if err != nil {
            return nil, err
        }
    
        return &secretKeyImpl{privKey, nil, kg.params.params, kg.params.rand}, nil
    }

    params

    type Params struct {
        Hash      func() hash.Hash
        hashAlgo  crypto.Hash //哈希加密
        Cipher    func([]byte) (cipher.Block, error) //暗号
        BlockSize int //块大小
        KeyLen    int //密钥长度
    }

    pk

    //获取随机密钥
    func (pk *publicKeyImpl) GetRand() io.Reader {
        return pk.rand
    }
    //判断是否为公钥
    func (pk *publicKeyImpl) IsPublic() bool {
        return true
    }

    sk

    func (sk *secretKeyImpl) IsPublic() bool {
        return false
    }
    
    func (sk *secretKeyImpl) GetRand() io.Reader {
        return sk.rand
    }
    
    func (sk *secretKeyImpl) GetPublicKey() ecies.PublicKey {
        if sk.pub == nil {
            sk.pub = &publicKeyImpl{&sk.priv.PublicKey, sk.rand, sk.params}
        }
        return sk.pub
    }
    //转换为字节
    func (sks *secretKeySerializerImpl) ToBytes(key interface{}) ([]byte, error) {
        switch sk := key.(type) {
        case *secretKeyImpl:
            return x509.MarshalECPrivateKey(sk.priv)
        default:
            return nil, ecies.ErrInvalidKeyParameter
        }
    
        return nil, ecies.ErrInvalidKeyParameter
    }
    //从字节中转换私钥
    func (sks *secretKeySerializerImpl) FromBytes(bytes []byte) (interface{}, error) {
        key, err := x509.ParseECPrivateKey(bytes)
        if err != nil {
            return nil, err
        }
    
        // TODO: add params here
        return &secretKeyImpl{key, nil, nil, rand.Reader}, nil
    }
    

    spi

    //序列化私钥
    func serializePrivateKey(priv ecies.PrivateKey) ([]byte, error) {
        serializer := secretKeySerializerImpl{}
        return serializer.ToBytes(priv)
    }
    //反序列化私钥
    func deserializePrivateKey(bytes []byte) (ecies.PrivateKey, error) {
        serializer := secretKeySerializerImpl{}
        priv, err := serializer.FromBytes(bytes)
        if err != nil {
            return nil, err
        }
    
        return priv.(ecies.PrivateKey), nil
    }
    //生成非对称密码
    func newAsymmetricCipher() (ecies.AsymmetricCipher, error) {
        return &encryptionSchemeImpl{}, nil
    }
    //生成私钥
    func newPrivateKey(rand io.Reader, curve elliptic.Curve) (ecies.PrivateKey, error) {
        kg, err := newKeyGeneratorFromCurve(rand, curve)
        if err != nil {
            return nil, err
        }
        return kg.GenerateKey()
    }
    //从私钥创建非对称密码
    func newAsymmetricCipherFromPrivateKey(priv ecies.PrivateKey) (ecies.AsymmetricCipher, error) {
        es, err := newAsymmetricCipher()
        if err != nil {
            return nil, err
        }
    
        err = es.Init(priv)
        if err != nil {
            return nil, err
        }
    
        return es, nil
    }
    //从公钥创建非对称密码
    func newAsymmetricCipherFromPublicKey(pub ecies.PublicKey) (ecies.AsymmetricCipher, error) {
        es, err := newAsymmetricCipher()
        if err != nil {
            return nil, err
        }
    
        err = es.Init(pub)
        if err != nil {
            return nil, err
        }
    
        return es, nil
    }

    crypto

    cypto实现了和密钥有关的接口

    var (
        // 无效的密钥参数
        ErrInvalidKeyParameter = errors.New("Invalid Key Parameter.")
    
        //无效的密钥生成器参数
        ErrInvalidKeyGeneratorParameter = errors.New("Invalid Key Generator Parameter.")
    )
    
    // 对于所有参数的通用接口
    type Parameters interface {
    
        // 随机生成关联参数
        GetRand() io.Reader
    }
    
    // 通用接口来表示密码参数
    type CipherParameters interface {
        Parameters
    }
    
    // 通用接口来表示非对称密码参数
    type AsymmetricCipherParameters interface {
        Parameters
    
        // 如果参数是公开的返回true,否则为false。
        IsPublic() bool
    }
    
    //通用接口代表非对称公钥参数
    type PublicKey interface {
        AsymmetricCipherParameters
    }
    
    //通用接口代表非对称私钥参数
    type PrivateKey interface {
        AsymmetricCipherParameters
    
        // 返回关联公钥
        GetPublicKey() PublicKey
    }
    
    // 通用接口来表示密钥生成参数
    type KeyGeneratorParameters interface {
        Parameters
    }
    
    // 定义密钥生成器
    type KeyGenerator interface {
        //初始化生成使用传递的参数
        Init(params KeyGeneratorParameters) error
    
        // 生成一个新的私钥
        GenerateKey() (PrivateKey, error)
    }
    
    //定义了一个非对称密码
    type AsymmetricCipher interface {
        // 使用传递的参数初始化
        Init(params AsymmetricCipherParameters) error
    
        // 处理输入给出的字节数组的过程
        Process(msg []byte) ([]byte, error)
    }
    
    // 密钥序列化/反序列化
    type KeySerializer interface {
        // 转换密钥为字节
        ToBytes(key interface{}) ([]byte, error)
    
        // 转换字节为密钥
        FromBytes([]byte) (interface{}, error)
    }
    
    // ECIES服务提供接口
    type SPI interface {
    
        //从秘钥创建解密一个新的非对称密码
        NewAsymmetricCipherFromPrivateKey(priv PrivateKey) (AsymmetricCipher, error)
    
        //从公钥创建解密一个新的非对称密码
        NewAsymmetricCipherFromPublicKey(pub PublicKey) (AsymmetricCipher, error)
    
        // 从(rand, params)创建一个新的私钥
        NewPrivateKey(rand io.Reader, params interface{}) (PrivateKey, error)
    
        //从(rand, params)创建一个新的公钥
        NewPublicKey(rand io.Reader, params interface{}) (PublicKey, error)
    
        // 序列化私钥
        SerializePrivateKey(priv PrivateKey) ([]byte, error)
    
        // 反序列化私钥
        DeserializePrivateKey(bytes []byte) (PrivateKey, error)
    }
    

    aes

    const (
        // AES 秘钥的默认长度
        AESKeyLength = 32
    
        // 默认nonce大小
        NonceSize    = 24
    )
    
    // 返回一个长度AESKeyLength为随机 AES 密钥
    func GenAESKey() ([]byte, error) {
        return GetRandomBytes(AESKeyLength)
    }
    
    //基于PKCS7标准填充
    func PKCS7Padding(src []byte) []byte {
        padding := aes.BlockSize - len(src)%aes.BlockSize
        padtext := bytes.Repeat([]byte{byte(padding)}, padding)
        return append(src, padtext...)
    }
    
    //基于PKCS7标准反填充
    func PKCS7UnPadding(src []byte) ([]byte, error) {
        length := len(src)
        unpadding := int(src[length-1])
    
        if unpadding > aes.BlockSize || unpadding == 0 {
            return nil, fmt.Errorf("invalid padding")
        }
    
        pad := src[len(src)-unpadding:]
        for i := 0; i < unpadding; i++ {
            if pad[i] != byte(unpadding) {
                return nil, fmt.Errorf("invalid padding")
            }
        }
    
        return src[:(length - unpadding)], nil
    }
    
    //使用CBC模式加密
    func CBCEncrypt(key, s []byte) ([]byte, error) {
        // CBC模式适用于块,这样的明文可能需要填充到下一个整块。对于这种填充的一个实例,参见
        // https://tools.ietf.org/html/rfc5246#section-6.2.3.2. Here we'll
        // 假定所述明文已确定长度。
        if len(s)%aes.BlockSize != 0 {
            return nil, errors.New("plaintext is not a multiple of the block size")
        }
    
        block, err := aes.NewCipher(key)
        if err != nil {
            return nil, err
        }
    
        // 需要唯一,但并不安全。因此它是常见的包括其在密文的开始。
        ciphertext := make([]byte, aes.BlockSize+len(s))
        iv := ciphertext[:aes.BlockSize]
        if _, err := io.ReadFull(rand.Reader, iv); err != nil {
            return nil, err
        }
    
        mode := cipher.NewCBCEncrypter(block, iv)
        mode.CryptBlocks(ciphertext[aes.BlockSize:], s)
    
        // 要记住,密文必须经过验证是非常重要的(即,通过使用加密/ HMAC)以及为了被加密是安全的。
        return ciphertext, nil
    }
    
    // 使用CBC模式解密
    func CBCDecrypt(key, src []byte) ([]byte, error) {
        block, err := aes.NewCipher(key)
        if err != nil {
            return nil, err
        }
    
        // 需要唯一,但并不安全。因此它是常见的包括其在密文的开始。
        if len(src) < aes.BlockSize {
            return nil, errors.New("ciphertext too short")
        }
        iv := src[:aes.BlockSize]
        src = src[aes.BlockSize:]
    
        //CBC模式往往工作于整个块中
        if len(src)%aes.BlockSize != 0 {
            return nil, errors.New("ciphertext is not a multiple of the block size")
        }
    
        mode := cipher.NewCBCDecrypter(block, iv)
    
        //可以就地工作,如果两个参数是相同的。
        mode.CryptBlocks(src, src)
    
        // 如果原来的明文的长度不是块大小的倍数,加密填充时,这将在这一点被移除被添加
    
    
        return src, nil
    }
    
    // 结合CBC加密填充PKCS7
    func CBCPKCS7Encrypt(key, src []byte) ([]byte, error) {
        return CBCEncrypt(key, PKCS7Padding(src))
    }
    
    //结合CBC加密反填充填充PKCS7
    func CBCPKCS7Decrypt(key, src []byte) ([]byte, error) {
        pt, err := CBCDecrypt(key, src)
        if err != nil {
            return nil, err
        }
    
        original, err := PKCS7UnPadding(pt)
        if err != nil {
            return nil, err
        }
    
        return original, nil
    }
    

    cert

    var (
        // TCertEncTCertIndex为TCertIndex的对象标识符
        TCertEncTCertIndex = asn1.ObjectIdentifier{1, 2, 3, 4, 5, 6, 7}
    )
    
    // 将der转换为X509
    func DERToX509Certificate(asn1Data []byte) (*x509.Certificate, error) {
        return x509.ParseCertificate(asn1Data)
    }
    
    //  将pem转换为X509
    func PEMtoCertificate(raw []byte) (*x509.Certificate, error) {
        block, _ := pem.Decode(raw)
        if block == nil {
            return nil, errors.New("No PEM block available")
        }
    
        if block.Type != "CERTIFICATE" || len(block.Headers) != 0 {
            return nil, errors.New("Not a valid CERTIFICATE PEM block")
        }
    
        cert, err := x509.ParseCertificate(block.Bytes)
        if err != nil {
            return nil, err
        }
    
        return cert, nil
    }
    
    // 将 pem 转换为der
    func PEMtoDER(raw []byte) ([]byte, error) {
        block, _ := pem.Decode(raw)
        if block == nil {
            return nil, errors.New("No PEM block available")
        }
    
        if block.Type != "CERTIFICATE" || len(block.Headers) != 0 {
            return nil, errors.New("Not a valid CERTIFICATE PEM block")
        }
    
        return block.Bytes, nil
    }
    
    // 将 pem 转换为x509和der
    func PEMtoCertificateAndDER(raw []byte) (*x509.Certificate, []byte, error) {
        block, _ := pem.Decode(raw)
        if block == nil {
            return nil, nil, errors.New("No PEM block available")
        }
    
        if block.Type != "CERTIFICATE" || len(block.Headers) != 0 {
            return nil, nil, errors.New("Not a valid CERTIFICATE PEM block")
        }
    
        cert, err := x509.ParseCertificate(block.Bytes)
        if err != nil {
            return nil, nil, err
        }
    
        return cert, block.Bytes, nil
    }
    
    // 将der转换为pem
    func DERCertToPEM(der []byte) []byte {
        return pem.EncodeToMemory(
            &pem.Block{
                Type:  "CERTIFICATE",
                Bytes: der,
            },
        )
    }
    
    // 返回请求的关键扩展。这也从未处理的关键扩展的列表中移除
    func GetCriticalExtension(cert *x509.Certificate, oid asn1.ObjectIdentifier) ([]byte, error) {
        for i, ext := range cert.UnhandledCriticalExtensions {
            if IntArrayEquals(ext, oid) {
                cert.UnhandledCriticalExtensions = append(cert.UnhandledCriticalExtensions[:i], cert.UnhandledCriticalExtensions[i+1:]...)
    
                break
            }
        }
    
        for _, ext := range cert.Extensions {
            if IntArrayEquals(ext.Id, oid) {
                return ext.Value, nil
            }
        }
    
        return nil, errors.New("Failed retrieving extension.")
    }
    
    // 创建一个自签名证书
    func NewSelfSignedCert() ([]byte, interface{}, error) {
        privKey, err := NewECDSAKey()
        if err != nil {
            return nil, nil, err
        }
    
        testExtKeyUsage := []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth}
        testUnknownExtKeyUsage := []asn1.ObjectIdentifier{[]int{1, 2, 3}, []int{2, 59, 1}}
        extraExtensionData := []byte("extra extension")
        commonName := "test.example.com"
        template := x509.Certificate{
            SerialNumber: big.NewInt(1),
            Subject: pkix.Name{
                CommonName:   commonName,
                Organization: []string{"Σ Acme Co"},
                Country:      []string{"US"},
                ExtraNames: []pkix.AttributeTypeAndValue{
                    {
                        Type:  []int{2, 5, 4, 42},
                        Value: "Gopher",
                    },
                    // 应该全部覆盖Country.
                    {
                        Type:  []int{2, 5, 4, 6},
                        Value: "NL",
                    },
                },
            },
            NotBefore: time.Unix(1000, 0),
            NotAfter:  time.Unix(100000, 0),
    
            SignatureAlgorithm: x509.ECDSAWithSHA384,
    
            SubjectKeyId: []byte{1, 2, 3, 4},
            KeyUsage:     x509.KeyUsageCertSign,
    
            ExtKeyUsage:        testExtKeyUsage,
            UnknownExtKeyUsage: testUnknownExtKeyUsage,
    
            BasicConstraintsValid: true,
            IsCA: true,
    
            OCSPServer:            []string{"http://ocsp.example.com"},
            IssuingCertificateURL: []string{"http://crt.example.com/ca1.crt"},
    
            DNSNames:       []string{"test.example.com"},
            EmailAddresses: []string{"gopher@golang.org"},
            IPAddresses:    []net.IP{net.IPv4(127, 0, 0, 1).To4(), net.ParseIP("2001:4860:0:2001::68")},
    
            PolicyIdentifiers:   []asn1.ObjectIdentifier{[]int{1, 2, 3}},
            PermittedDNSDomains: []string{".example.com", "example.com"},
    
            CRLDistributionPoints: []string{"http://crl1.example.com/ca1.crl", "http://crl2.example.com/ca1.crl"},
    
            ExtraExtensions: []pkix.Extension{
                {
                    Id:    []int{1, 2, 3, 4},
                    Value: extraExtensionData,
                },
            },
        }
    
        cert, err := x509.CreateCertificate(rand.Reader, &template, &template, &privKey.PublicKey, privKey)
        if err != nil {
            return nil, nil, err
        }
    
        return cert, privKey, nil
    }
    
    //通过密钥检查证书的公钥
    func CheckCertPKAgainstSK(x509Cert *x509.Certificate, privateKey interface{}) error {
        switch pub := x509Cert.PublicKey.(type) {
        case *rsa.PublicKey:
            priv, ok := privateKey.(*rsa.PrivateKey)
            if !ok {
                return errors.New("Private key type does not match public key type")
            }
            if pub.N.Cmp(priv.N) != 0 {
                return errors.New("Private key does not match public key")
            }
        case *ecdsa.PublicKey:
            priv, ok := privateKey.(*ecdsa.PrivateKey)
            if !ok {
                return errors.New("Private key type does not match public key type")
    
            }
            if pub.X.Cmp(priv.X) != 0 || pub.Y.Cmp(priv.Y) != 0 {
                return errors.New("Private key does not match public key")
            }
        default:
            return errors.New("Unknown public key algorithm")
        }
    
        return nil
    }
    
    // 检查证书的有效性通过certPool
    func CheckCertAgainRoot(x509Cert *x509.Certificate, certPool *x509.CertPool) ([][]*x509.Certificate, error) {
        opts := x509.VerifyOptions{
            // TODO     DNSName: "test.example.com",
            Roots: certPool,
        }
    
        return x509Cert.Verify(opts)
    }
    
    // 对检查合格的密钥和CertPool传递证书
    func CheckCertAgainstSKAndRoot(x509Cert *x509.Certificate, privateKey interface{}, certPool *x509.CertPool) error {
        if err := CheckCertPKAgainstSK(x509Cert, privateKey); err != nil {
            return err
        }
    
        if _, err := CheckCertAgainRoot(x509Cert, certPool); err != nil {
            return err
        }
    
        return nil
    }
    

    conf

    // 返回注册ID
    func (conf *NodeConfiguration) GetEnrollmentID() string {
        key := "tests.crypto.users." + conf.Name + ".enrollid"
        value := viper.GetString(key)
        if value == "" {
            panic(fmt.Errorf("Enrollment id not specified in configuration file. Please check that property '%s' is set", key))
        }
        return value
    }
    
    //返回注册密码
    func (conf *NodeConfiguration) GetEnrollmentPWD() string {
        key := "tests.crypto.users." + conf.Name + ".enrollpw"
        value := viper.GetString(key)
        if value == "" {
            panic(fmt.Errorf("Enrollment id not specified in configuration file. Please check that property '%s' is set", key))
        }
        return value
    }
    

    ecdsa

    // 表示ECDSA签名
    type ECDSASignature struct {
        R, S *big.Int
    }
    
    //生成一个新的ECDSA密钥
    func NewECDSAKey() (*ecdsa.PrivateKey, error) {
        return ecdsa.GenerateKey(conf.GetDefaultCurve(), rand.Reader)
    }
    
    // ECDSASignDirect 符号
    func ECDSASignDirect(signKey interface{}, msg []byte) (*big.Int, *big.Int, error) {
        temp := signKey.(*ecdsa.PrivateKey)
        h := Hash(msg)
        r, s, err := ecdsa.Sign(rand.Reader, temp, h)
        if err != nil {
            return nil, nil, err
        }
    
        return r, s, nil
    }
    
    // ECDSASign 符号
    func ECDSASign(signKey interface{}, msg []byte) ([]byte, error) {
        temp := signKey.(*ecdsa.PrivateKey)
        h := Hash(msg)
        r, s, err := ecdsa.Sign(rand.Reader, temp, h)
        if err != nil {
            return nil, err
        }
    
        //  R, _ := r.MarshalText()
        //  S, _ := s.MarshalText()
        //
        //  fmt.Printf("r [%s], s [%s]
    ", R, S)
    
        raw, err := asn1.Marshal(ECDSASignature{r, s})
        if err != nil {
            return nil, err
        }
    
        return raw, nil
    }
    
    //校验
    func ECDSAVerify(verKey interface{}, msg, signature []byte) (bool, error) {
        ecdsaSignature := new(ECDSASignature)
        _, err := asn1.Unmarshal(signature, ecdsaSignature)
        if err != nil {
            return false, nil
        }
    
        //  R, _ := ecdsaSignature.R.MarshalText()
        //  S, _ := ecdsaSignature.S.MarshalText()
        //  fmt.Printf("r [%s], s [%s]
    ", R, S)
    
        temp := verKey.(*ecdsa.PublicKey)
        h := Hash(msg)
        return ecdsa.Verify(temp, h, ecdsaSignature.R, ecdsaSignature.S), nil
    }
    
    // 测试签名功能
    func VerifySignCapability(tempSK interface{}, certPK interface{}) error {
        /* TODO: reactive or remove
        msg := []byte("This is a message to be signed and verified by ECDSA!")
    
        sigma, err := ECDSASign(tempSK, msg)
        if err != nil {
            //      log.Error("Error signing [%s].", err.Error())
    
            return err
        }
    
        ok, err := ECDSAVerify(certPK, msg, sigma)
        if err != nil {
            //      log.Error("Error verifying [%s].", err.Error())
    
            return err
        }
    
        if !ok {
            //      log.Error("Signature not valid.")
    
            return errors.New("Signature not valid.")
        }
    
        //  log.Info("Verifing signature capability...done")
        */
        return nil
    }
    

    hash

    // 返回一个新的散列函数
    func NewHash() hash.Hash {
        return conf.GetDefaultHash()()
    }
    
    // 散列使用预定义散列函数的MSH
    func Hash(msg []byte) []byte {
        hash := NewHash()
        hash.Write(msg)
        return hash.Sum(nil)
    }
    
    // hmacs x 使用密钥的密钥
    func HMAC(key, x []byte) []byte {
        mac := hmac.New(conf.GetDefaultHash(), key)
        mac.Write(x)
    
        return mac.Sum(nil)
    }
    
    // hmacs x 使用密钥的密钥,并截断
    func HMACTruncated(key, x []byte, truncation int) []byte {
        mac := hmac.New(conf.GetDefaultHash(), key)
        mac.Write(x)
    
        return mac.Sum(nil)[:truncation]
    }
    

    io

    // 检查一个目录是否丢失或为空
    func DirMissingOrEmpty(path string) (bool, error) {
        dirExists, err := DirExists(path)
        if err != nil {
            return false, err
        }
        if !dirExists {
            return true, nil
        }
    
        dirEmpty, err := DirEmpty(path)
        if err != nil {
            return false, err
        }
        if dirEmpty {
            return true, nil
        }
        return false, nil
    }
    
    // 检查一个目录是否存在
    func DirExists(path string) (bool, error) {
        _, err := os.Stat(path)
        if err == nil {
            return true, nil
        }
        if os.IsNotExist(err) {
            return false, nil
        }
        return false, err
    }
    
    // 检查一个目录是否为空
    func DirEmpty(path string) (bool, error) {
        f, err := os.Open(path)
        if err != nil {
            return false, err
        }
        defer f.Close()
    
        _, err = f.Readdir(1)
        if err == io.EOF {
            return true, nil
        }
        return false, err
    }
    
    // 检查一个文件是否丢失
    func FileMissing(path string, name string) (bool, error) {
        _, err := os.Stat(filepath.Join(path, name))
        if err != nil {
            return true, err
        }
        return false, nil
    }
    
    // 如果路径丢失返回true,否则返回false
    func FilePathMissing(path string) (bool, error) {
        _, err := os.Stat(path)
        if err != nil {
            return true, err
        }
        return false, nil
    }
    
    // Base64解码
    func DecodeBase64(in string) ([]byte, error) {
        return base64.StdEncoding.DecodeString(in)
    }
    
    // Base64编码
    func EncodeBase64(in []byte) string {
        return base64.StdEncoding.EncodeToString(in)
    }
    
    //检查整数的阵列是否相同
    func IntArrayEquals(a []int, b []int) bool {
        if len(a) != len(b) {
            return false
        }
        for i, v := range a {
            if v != b[i] {
                return false
            }
        }
        return true
    }
    
    // 检查 tcp端口是否打开
    func IsTCPPortOpen(laddr string) error {
        lis, err := net.Listen("tcp", laddr)
        if err != nil {
            return err
        }
        lis.Close()
        return nil
    }
    
    var seed uint32
    var randmu sync.Mutex
    
    func reseed() uint32 {
        return uint32(time.Now().UnixNano() + int64(os.Getpid()))
    }
    
    func nextSuffix() string {
        randmu.Lock()
        r := seed
        if r == 0 {
            r = reseed()
        }
        r = r*1664525 + 1013904223 // constants from Numerical Recipes
        seed = r
        randmu.Unlock()
        return strconv.Itoa(int(1e9 + r%1e9))[1:]
    }
    
    // 返回一个临时文件的路径与关于系统的临时目录.
    func TempFile(dir, prefix string) (name string, err error) {
        if dir == "" {
            dir = os.TempDir()
        }
    
        nconflict := 0
        for i := 0; i < 10000; i++ {
            name = filepath.Join(dir, prefix+nextSuffix())
            f, err := os.Stat(name)
            if f != nil || os.IsExist(err) {
                if nconflict++; nconflict > 10 {
                    randmu.Lock()
                    seed = reseed()
                    randmu.Unlock()
                }
                continue
            }
            break
        }
        return
    }
    

    math

    // 返回x的绝对值
    func Abs(x int) int {
        if x < 0 {
            return -x
        }
        return x
    }
    

    random

    返回随机寻找的字节的长度

    func GetRandomBytes(len int) ([]byte, error) {
        key := make([]byte, len)
    
        _, err := rand.Read(key)
        if err != nil {
            return nil, err
        }
    
        return key, nil
    }

    slice

    // 通过切片克隆
    func Clone(src []byte) []byte {
        clone := make([]byte, len(src))
        copy(clone, src)
    
        return clone
    }
    

    keys

    // 为der反串行化为私钥
    func PrivateKeyToDER(privateKey *ecdsa.PrivateKey) ([]byte, error) {
        return x509.MarshalECPrivateKey(privateKey)
    }
    
    // 将私钥转换为PEM
    func PrivateKeyToPEM(privateKey interface{}, pwd []byte) ([]byte, error) {
        if len(pwd) != 0 {
            return PrivateKeyToEncryptedPEM(privateKey, pwd)
        }
    
        switch x := privateKey.(type) {
        case *ecdsa.PrivateKey:
            raw, err := x509.MarshalECPrivateKey(x)
    
            if err != nil {
                return nil, err
            }
    
            return pem.EncodeToMemory(
                &pem.Block{
                    Type:  "ECDSA PRIVATE KEY",
                    Bytes: raw,
                },
            ), nil
        default:
            return nil, ErrInvalidKey
        }
    }
    
    // 将私钥转换为加密PEM
    func PrivateKeyToEncryptedPEM(privateKey interface{}, pwd []byte) ([]byte, error) {
        switch x := privateKey.(type) {
        case *ecdsa.PrivateKey:
            raw, err := x509.MarshalECPrivateKey(x)
    
            if err != nil {
                return nil, err
            }
    
            block, err := x509.EncryptPEMBlock(
                rand.Reader,
                "ECDSA PRIVATE KEY",
                raw,
                pwd,
                x509.PEMCipherAES256)
    
            if err != nil {
                return nil, err
            }
    
            return pem.EncodeToMemory(block), nil
    
        default:
            return nil, ErrInvalidKey
        }
    }
    
    // 将der串行化为私钥
    func DERToPrivateKey(der []byte) (key interface{}, err error) {
        //fmt.Printf("DER [%s]
    ", EncodeBase64(der))
    
        if key, err = x509.ParsePKCS1PrivateKey(der); err == nil {
            return key, nil
        }
        //fmt.Printf("DERToPrivateKey Err [%s]
    ", err)
        if key, err = x509.ParsePKCS8PrivateKey(der); err == nil {
            switch key.(type) {
            case *rsa.PrivateKey, *ecdsa.PrivateKey:
                return
            default:
                return nil, errors.New("Found unknown private key type in PKCS#8 wrapping")
            }
        }
        //fmt.Printf("DERToPrivateKey Err [%s]
    ", err)
        if key, err = x509.ParseECPrivateKey(der); err == nil {
            return
        }
        //fmt.Printf("DERToPrivateKey Err [%s]
    ", err)
    
        return nil, errors.New("Failed to parse private key")
    }
    
    // 将pem串行化为私钥
    func PEMtoPrivateKey(raw []byte, pwd []byte) (interface{}, error) {
        block, _ := pem.Decode(raw)
    
        // 从头部导出密钥的类型
    
        if x509.IsEncryptedPEMBlock(block) {
            if pwd == nil {
                return nil, errors.New("Encrypted Key. Need a password!!!")
            }
    
            decrypted, err := x509.DecryptPEMBlock(block, pwd)
            if err != nil {
                return nil, errors.New("Failed decryption!!!")
            }
    
            key, err := DERToPrivateKey(decrypted)
            if err != nil {
                return nil, err
            }
            return key, err
        }
    
        cert, err := DERToPrivateKey(block.Bytes)
        if err != nil {
            return nil, err
        }
        return cert, err
    }
    
    // 从PEM提取一个AES密钥
    func PEMtoAES(raw []byte, pwd []byte) ([]byte, error) {
        block, _ := pem.Decode(raw)
    
        if x509.IsEncryptedPEMBlock(block) {
            if pwd == nil {
                return nil, errors.New("Encrypted Key. Need a password!!!")
            }
    
            decrypted, err := x509.DecryptPEMBlock(block, pwd)
            if err != nil {
                return nil, err
            }
            return decrypted, nil
        }
    
        return block.Bytes, nil
    }
    
    // 将AES封装为PEM格式
    func AEStoPEM(raw []byte) []byte {
        return pem.EncodeToMemory(&pem.Block{Type: "AES PRIVATE KEY", Bytes: raw})
    }
    
    //将AES封装为加密PEM格式
    func AEStoEncryptedPEM(raw []byte, pwd []byte) ([]byte, error) {
        if len(pwd) == 0 {
            return AEStoPEM(raw), nil
        }
    
        block, err := x509.EncryptPEMBlock(
            rand.Reader,
            "AES PRIVATE KEY",
            raw,
            pwd,
            x509.PEMCipherAES256)
    
        if err != nil {
            return nil, err
        }
    
        return pem.EncodeToMemory(block), nil
    }
    
    
    
    // 将公钥反串行化为pem格式
    func PublicKeyToPEM(publicKey interface{}, pwd []byte) ([]byte, error) {
        if len(pwd) != 0 {
            return PublicKeyToEncryptedPEM(publicKey, pwd)
        }
    
        switch x := publicKey.(type) {
        case *ecdsa.PublicKey:
            PubASN1, err := x509.MarshalPKIXPublicKey(x)
            if err != nil {
                return nil, err
            }
    
            return pem.EncodeToMemory(
                &pem.Block{
                    Type:  "ECDSA PUBLIC KEY",
                    Bytes: PubASN1,
                },
            ), nil
    
        default:
            return nil, ErrInvalidKey
        }
    }
    
    // 将公钥转换为加密pem
    func PublicKeyToEncryptedPEM(publicKey interface{}, pwd []byte) ([]byte, error) {
        switch x := publicKey.(type) {
        case *ecdsa.PublicKey:
            raw, err := x509.MarshalPKIXPublicKey(x)
    
            if err != nil {
                return nil, err
            }
    
            block, err := x509.EncryptPEMBlock(
                rand.Reader,
                "ECDSA PUBLIC KEY",
                raw,
                pwd,
                x509.PEMCipherAES256)
    
            if err != nil {
                return nil, err
            }
    
            return pem.EncodeToMemory(block), nil
    
        default:
            return nil, ErrInvalidKey
        }
    }
    
    // 将pem串行化为公钥
    func PEMtoPublicKey(raw []byte, pwd []byte) (interface{}, error) {
        block, _ := pem.Decode(raw)
        fmt.Printf("block % x
    ", raw)
    
    
        if x509.IsEncryptedPEMBlock(block) {
            if pwd == nil {
                return nil, errors.New("Encrypted Key. Need a password!!!")
            }
    
            decrypted, err := x509.DecryptPEMBlock(block, pwd)
            if err != nil {
                return nil, errors.New("Failed decryption!!!")
            }
    
            key, err := DERToPublicKey(decrypted)
            if err != nil {
                return nil, err
            }
            return key, err
        }
    
        cert, err := DERToPublicKey(block.Bytes)
        if err != nil {
            return nil, err
        }
        return cert, err
    }
    
    //将der串行化为公钥
    func DERToPublicKey(derBytes []byte) (pub interface{}, err error) {
        key, err := x509.ParsePKIXPublicKey(derBytes)
    
        return key, err
    }
    
  • 相关阅读:
    ftp-server(对象存储)
    zabbix监控VMware6.7
    linux安装中文字体
    vsftpd不支持目录软链接的解决办法
    linux内网IP如果判断出网IP地址
    mysql ANSI_QUOTES 这个sql_mode的作用(字段可以使用双引号)
    查看tomcat项目中,具体占用cpu高的线程。
    nginx ssl 自签证书实验
    Redis复制和哨兵部署
    利用Python脚本备份服务器上所有PostgreSQL数据库
  • 原文地址:https://www.cnblogs.com/ainima/p/6331785.html
Copyright © 2011-2022 走看看