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\n", utils.EncodeBase64(Rx.Bytes()))
    //fmt.Printf("Ry %s\n", 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\n", 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\n", utils.EncodeBase64(Rb))
    //fmt.Printf("EM %s\n", utils.EncodeBase64(EM))
    //fmt.Printf("D %s\n", 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\n")
    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\n", 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\n", utils.EncodeBase64(Rx.Bytes()))
    //fmt.Printf("Ry %s\n", utils.EncodeBase64(Ry.Bytes()))

    // 從暫時的私鑰k得出一個公鑰z,並轉換z到字節串Z
    z, _ := params.ScalarMult(Rx, Ry, priv.D.Bytes())
    Z := z.Bytes()
    //fmt.Printf("Z %s\n", 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\n", utils.EncodeBase64(ciphertext[mStart:mEnd]))
    //fmt.Printf("D' %s\n", utils.EncodeBase64(D))
    //fmt.Printf("D %s\n", 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{"[email protected]"},
        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]\n", 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]\n", 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]\n", EncodeBase64(der))

    if key, err = x509.ParsePKCS1PrivateKey(der); err == nil {
        return key, nil
    }
    //fmt.Printf("DERToPrivateKey Err [%s]\n", 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]\n", err)
    if key, err = x509.ParseECPrivateKey(der); err == nil {
        return
    }
    //fmt.Printf("DERToPrivateKey Err [%s]\n", 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\n", 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
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章