├── sm3
├── ifile
├── sm3_test.go
└── sm3.go
├── gmtls
├── websvr
│ ├── img
│ │ └── autoswitchlogic.png
│ ├── certs
│ │ ├── SM2_CA_KEY.pem
│ │ ├── sm2_auth_key.pem
│ │ ├── sm2_enc_key.pem
│ │ ├── sm2_sign_key.pem
│ │ ├── SM2_CA.cer
│ │ ├── sm2_enc_cert.cer
│ │ ├── sm2_auth_cert.cer
│ │ ├── sm2_sign_cert.cer
│ │ ├── rsa_auth_cert.cer
│ │ ├── RSA_CA.cer
│ │ ├── rsa_sign.cer
│ │ ├── rsa_auth_key.pem
│ │ ├── rsa_sign_key.pem
│ │ └── RSA_CA_KEY.pem
│ ├── websvr_test.go
│ ├── websvr.go
│ └── README.md
├── gmcredentials
│ ├── testdata
│ │ ├── sign.key
│ │ ├── user.key
│ │ ├── encrypt.key
│ │ ├── ca.cert
│ │ ├── user.cert
│ │ ├── encrypt.cert
│ │ └── sign.cert
│ ├── echo
│ │ ├── echo.proto
│ │ └── echo.pb.go
│ ├── credentials_util_go18.go
│ ├── credentials_test.go
│ └── credentials.go
├── auto_switch_config.go
├── simple_round_trip.go
├── http_client.go
├── gm_handshake_messages.go
├── alert.go
├── auth.go
├── ticket.go
└── http_client_test.go
├── go.mod
├── .gitignore
├── pkcs12
├── errors.go
├── mac.go
├── bmp-string.go
├── pkcs12_test.go
├── safebags.go
├── crypto.go
├── pbkdf.go
├── rc2.go
└── pkcs8.go
├── .travis.yml
├── azure-pipelines.yml
├── sm4
├── padding
│ ├── bloc_cryptor_test.go
│ ├── bloc_cryptor.go
│ ├── pkcs7_padding_io_test.go
│ ├── README.md
│ └── pkcs7_padding_io.go
├── sm4_gcm_test.go
├── utils.go
├── sm4_test.go
└── sm4_gcm.go
├── sm2
├── utils.go
└── sm2_test.go
├── README.md
├── CHANGELOG.md
├── API使用说明.md
├── x509
├── pkcs1.go
├── pkcs7_test.go
├── cert_pool.go
├── ber.go
└── utils.go
└── go.sum
/sm3/ifile:
--------------------------------------------------------------------------------
1 | test
--------------------------------------------------------------------------------
/gmtls/websvr/img/autoswitchlogic.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tjfoc/gmsm/HEAD/gmtls/websvr/img/autoswitchlogic.png
--------------------------------------------------------------------------------
/go.mod:
--------------------------------------------------------------------------------
1 | module github.com/tjfoc/gmsm
2 |
3 | go 1.14
4 |
5 | require (
6 | github.com/golang/protobuf v1.4.2
7 | golang.org/x/crypto v0.0.0-20201012173705-84dcc777aaee
8 | golang.org/x/net v0.0.0-20201010224723-4f7140c49acb
9 | google.golang.org/grpc v1.31.0
10 | )
11 |
--------------------------------------------------------------------------------
/gmtls/gmcredentials/testdata/sign.key:
--------------------------------------------------------------------------------
1 | -----BEGIN PRIVATE KEY-----
2 | MIGHAgEAMBMGByqGSM49AgEGCCqBHM9VAYItBG0wawIBAQQgxG5EaEBHaq1vHL2D
3 | DOEQ9dCa3nqSXxBs4ZHIVH7sOaahRANCAASqGDkM9U2uwvaRceBzqFmtQTLmhQaW
4 | sGtA6QBD4jlZ0Vog13HVHEhTXbnaJYsfVjoxIK0ZGdKIgzK7gSUbVeLp
5 | -----END PRIVATE KEY-----
6 |
--------------------------------------------------------------------------------
/gmtls/gmcredentials/testdata/user.key:
--------------------------------------------------------------------------------
1 | -----BEGIN PRIVATE KEY-----
2 | MIGHAgEAMBMGByqGSM49AgEGCCqBHM9VAYItBG0wawIBAQQg9wokbsEkt3Y7V1/x
3 | acjfxL4xyBjtFyJU4EEi2GF/OIChRANCAATonWvfNyA4L44dhOmXXNuATGnlwwFb
4 | txoNVms+FiIw7yP5NEkHmbhMAjiANvrx3W3BhTtXmdYWclMKzr6xwd54
5 | -----END PRIVATE KEY-----
6 |
--------------------------------------------------------------------------------
/gmtls/gmcredentials/testdata/encrypt.key:
--------------------------------------------------------------------------------
1 | -----BEGIN PRIVATE KEY-----
2 | MIGHAgEAMBMGByqGSM49AgEGCCqBHM9VAYItBG0wawIBAQQg44YAGQHnMf28yNaI
3 | 4yuSoA4VQYfaz8RF47VFeSnbbgGhRANCAAT/RTpRPyZ2AqaNl3EO+YzgGf51lriY
4 | qhwp7OfDD+SF5jUquSaoC2L51zbH9FtCRkGMJW0+kBerZ17d86h7cxlM
5 | -----END PRIVATE KEY-----
6 |
--------------------------------------------------------------------------------
/gmtls/gmcredentials/echo/echo.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package echo;
4 |
5 | service Echo{
6 | rpc Echo(EchoRequest) returns (EchoResponse){}
7 | }
8 |
9 | message EchoRequest{
10 | string req = 1;
11 | }
12 |
13 | message EchoResponse{
14 | string result = 1;
15 | }
16 |
--------------------------------------------------------------------------------
/gmtls/websvr/certs/SM2_CA_KEY.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN PRIVATE KEY-----
2 | MIGTAgEAMBMGByqGSM49AgEGCCqBHM9VAYItBHkwdwIBAQQg8/o/oC+JT0Nv2T0K
3 | AdZ8OiH9YGVIGsnx0xfDK+lXzpagCgYIKoEcz1UBgi2hRANCAAS6OFCNygoH2f4O
4 | nPbV570rydtVcTvAUYOo/Mk9dcKsvEwDu+WZ2Lw8Ef4PCcqgm6B6+qo86x4AKXjm
5 | pTzXvXf9
6 | -----END PRIVATE KEY-----
7 |
--------------------------------------------------------------------------------
/gmtls/websvr/certs/sm2_auth_key.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN PRIVATE KEY-----
2 | MIGTAgEAMBMGByqGSM49AgEGCCqBHM9VAYItBHkwdwIBAQQgqSvMdgsT9VlcC7fF
3 | uewfAWp4eNoLT3zhTZisHsZ2WS+gCgYIKoEcz1UBgi2hRANCAAQVZNo44m183rOc
4 | 7tZ4qHL0tnYSL1RXnzdXCiUfH36Kku1yJ9DKKm6f5BtOPUzWx3YEy0UrrzXucie1
5 | PdwKFtWm
6 | -----END PRIVATE KEY-----
7 |
--------------------------------------------------------------------------------
/gmtls/websvr/certs/sm2_enc_key.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN PRIVATE KEY-----
2 | MIGTAgEAMBMGByqGSM49AgEGCCqBHM9VAYItBHkwdwIBAQQgb8tUl8wJ17FqiOSp
3 | pHwKa1pOgxQhAP0VoPe/EU0cGAqgCgYIKoEcz1UBgi2hRANCAARipb11eBDLluL8
4 | OMWZOfdyOXKsvWMu40pEW2nFdUPxWpRw+akHNz8Aat6Mbr5k9fUiG3gbC/SYG44t
5 | d40YCWFb
6 | -----END PRIVATE KEY-----
7 |
--------------------------------------------------------------------------------
/gmtls/websvr/certs/sm2_sign_key.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN PRIVATE KEY-----
2 | MIGTAgEAMBMGByqGSM49AgEGCCqBHM9VAYItBHkwdwIBAQQguBgnxgDxfYC9AM3v
3 | C2oQ7W54T7XLS3Dfoiv/8bQQXZ2gCgYIKoEcz1UBgi2hRANCAAQGNFBLmSXwgypy
4 | AFln6qlgaV+a6H1RaTBrpF12ciuY+bna9ewBXbAdM2wYPBxq8ifZfl/TngvX8TAq
5 | rNwx8prv
6 | -----END PRIVATE KEY-----
7 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | #Ignore thumbnails created by Windows
3 | Thumbs.db
4 | #Ignore files built by Visual Studio
5 | *.obj
6 | *.exe
7 | *.pdb
8 | *.user
9 | *.aps
10 | *.pch
11 | *.vspscc
12 | *_i.c
13 | *_p.c
14 | *.ncb
15 | *.suo
16 | *.tlb
17 | *.tlh
18 | *.bak
19 | *.cache
20 | *.ilk
21 | *.log
22 | [Bb]in
23 | [Dd]ebug*/
24 | *.lib
25 | *.sbr
26 | obj/
27 | [Rr]elease*/
28 | _ReSharper*/
29 | [Tt]est[Rr]esult*
30 | .vs/
31 | #Nuget packages folder
32 | packages/
33 | *.pem
34 | .idea
--------------------------------------------------------------------------------
/gmtls/websvr/certs/SM2_CA.cer:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | MIIB3jCCAYOgAwIBAgIIAs4Fs2xzPucwCgYIKoEcz1UBg3UwQjELMAkGA1UEBhMC
3 | Q04xDzANBgNVBAgMBua1meaxnzEPMA0GA1UEBwwG5p2t5beeMREwDwYDVQQKDAjm
4 | tYvor5VDQTAeFw0yMTA1MzAwNjU1MDJaFw0zMTA1MzAwNjU1MDJaMEIxCzAJBgNV
5 | BAYTAkNOMQ8wDQYDVQQIDAbmtZnmsZ8xDzANBgNVBAcMBuadreW3njERMA8GA1UE
6 | CgwI5rWL6K+VQ0EwWTATBgcqhkjOPQIBBggqgRzPVQGCLQNCAAS6OFCNygoH2f4O
7 | nPbV570rydtVcTvAUYOo/Mk9dcKsvEwDu+WZ2Lw8Ef4PCcqgm6B6+qo86x4AKXjm
8 | pTzXvXf9o2MwYTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNV
9 | HQ4EFgQUkdPXpvl7d/x5XcvSMqy7QASw+P8wHwYDVR0jBBgwFoAUkdPXpvl7d/x5
10 | XcvSMqy7QASw+P8wCgYIKoEcz1UBg3UDSQAwRgIhAO5iMN3sedKg0z6yk4SVnkNm
11 | 0c8FGV/Ttoa9N+hUlC2RAiEA2TdKM4glaYOdXIDoFTbmIeFZp/2Hxk3JWYpef8m+
12 | AP0=
13 | -----END CERTIFICATE-----
14 |
--------------------------------------------------------------------------------
/gmtls/websvr/certs/sm2_enc_cert.cer:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | MIIB4zCCAYqgAwIBAgIIAs4Fs4MsOxcwCgYIKoEcz1UBg3UwQjELMAkGA1UEBhMC
3 | Q04xDzANBgNVBAgMBua1meaxnzEPMA0GA1UEBwwG5p2t5beeMREwDwYDVQQKDAjm
4 | tYvor5VDQTAeFw0yMTA1MzAxMDM2MjRaFw0zMTA1MzAwNjU1MDJaMFoxCzAJBgNV
5 | BAYTAkNOMQ8wDQYDVQQIDAbmtZnmsZ8xDzANBgNVBAcMBuadreW3njEVMBMGA1UE
6 | CgwM5rWL6K+V5YWs5Y+4MRIwEAYDVQQDEwlsb2NhbGhvc3QwWTATBgcqhkjOPQIB
7 | BggqgRzPVQGCLQNCAARipb11eBDLluL8OMWZOfdyOXKsvWMu40pEW2nFdUPxWpRw
8 | +akHNz8Aat6Mbr5k9fUiG3gbC/SYG44td40YCWFbo1IwUDAOBgNVHQ8BAf8EBAMC
9 | BDAwHQYDVR0OBBYEFGzJ+VHUzO6lbLYBkkmlYXvJawiLMB8GA1UdIwQYMBaAFJHT
10 | 16b5e3f8eV3L0jKsu0AEsPj/MAoGCCqBHM9VAYN1A0cAMEQCIA1D0uErueuHk9pa
11 | Q/QYFKr5fDqM3NmSkw8C2AdUB3fQAiAuInwpog9I1wpBAojaGuNlpUroCUnMf1TO
12 | yYtCmmMgTw==
13 | -----END CERTIFICATE-----
14 |
--------------------------------------------------------------------------------
/gmtls/websvr/certs/sm2_auth_cert.cer:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | MIIB7zCCAZSgAwIBAgIIAs4GXZKiyLcwCgYIKoEcz1UBg3UwQjELMAkGA1UEBhMC
3 | Q04xDzANBgNVBAgMBua1meaxnzEPMA0GA1UEBwwG5p2t5beeMREwDwYDVQQKDAjm
4 | tYvor5VDQTAeFw0yMTA2MDMxNDQwMTFaFw0zMTA1MzAwNjU1MDJaMEUxCzAJBgNV
5 | BAYTAkNOMQ8wDQYDVQQIDAbmtZnmsZ8xDzANBgNVBAcMBuadreW3njEUMBIGA1UE
6 | AxMLY2xpZW50IGF1dGgwWTATBgcqhkjOPQIBBggqgRzPVQGCLQNCAAQVZNo44m18
7 | 3rOc7tZ4qHL0tnYSL1RXnzdXCiUfH36Kku1yJ9DKKm6f5BtOPUzWx3YEy0UrrzXu
8 | cie1PdwKFtWmo3EwbzAOBgNVHQ8BAf8EBAMCBsAwHQYDVR0lBBYwFAYIKwYBBQUH
9 | AwEGCCsGAQUFBwMCMB0GA1UdDgQWBBQhXmk/MqqLj+FwJxB/1ETt8OPxJTAfBgNV
10 | HSMEGDAWgBSR09em+Xt3/Hldy9IyrLtABLD4/zAKBggqgRzPVQGDdQNJADBGAiEA
11 | xSFUrnvdHCbljJK8ng5o2ONOtOQdDdWsKSNqKszsULQCIQCNdt/DOCL5NAuro3vy
12 | ND0QommjjXvYTX1ku2k903oLog==
13 | -----END CERTIFICATE-----
14 |
--------------------------------------------------------------------------------
/gmtls/gmcredentials/testdata/ca.cert:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | MIIB9DCCAZqgAwIBAgIJAMQooIBlaTnvMAoGCCqBHM9VAYN1ME0xCzAJBgNVBAYT
3 | AkNOMRIwEAYDVQQIDAlTaGFuZyBIYWkxFDASBgNVBAoMC2V4YW1wbGUuY29tMRQw
4 | EgYDVQQDDAtleGFtcGxlLmNvbTAeFw0yMDEwMjYxNDI3MjlaFw0zMDEwMjQxNDI3
5 | MjlaME0xCzAJBgNVBAYTAkNOMRIwEAYDVQQIDAlTaGFuZyBIYWkxFDASBgNVBAoM
6 | C2V4YW1wbGUuY29tMRQwEgYDVQQDDAtleGFtcGxlLmNvbTBZMBMGByqGSM49AgEG
7 | CCqBHM9VAYItA0IABLELsuZvJIROBlgOYcokYjrtZeMRJCmXwX+ihD6vl/pOsqnj
8 | PmCOPi4CX8qfeXC9q1Q4eJMaKQ8iZEJBIUrd/FmjYzBhMB0GA1UdDgQWBBR471SI
9 | sesZy/B92W6NbWerioEcrTAfBgNVHSMEGDAWgBR471SIsesZy/B92W6NbWerioEc
10 | rTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAKBggqgRzPVQGDdQNI
11 | ADBFAiBG/puLQVoWKUwzdWln0wYuM8ELjZD+A5ivY5hMte3p7wIhAMfZwX2aqMGJ
12 | JFp6NJClZNEwQ/WJTJmb0ony73Q4f7tS
13 | -----END CERTIFICATE-----
14 |
--------------------------------------------------------------------------------
/gmtls/websvr/certs/sm2_sign_cert.cer:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | MIICAzCCAamgAwIBAgIIAs4Fs4MsM4cwCgYIKoEcz1UBg3UwQjELMAkGA1UEBhMC
3 | Q04xDzANBgNVBAgMBua1meaxnzEPMA0GA1UEBwwG5p2t5beeMREwDwYDVQQKDAjm
4 | tYvor5VDQTAeFw0yMTA1MzAxMDM2MjRaFw0zMTA1MzAwNjU1MDJaMFoxCzAJBgNV
5 | BAYTAkNOMQ8wDQYDVQQIDAbmtZnmsZ8xDzANBgNVBAcMBuadreW3njEVMBMGA1UE
6 | CgwM5rWL6K+V5YWs5Y+4MRIwEAYDVQQDEwlsb2NhbGhvc3QwWTATBgcqhkjOPQIB
7 | BggqgRzPVQGCLQNCAAQGNFBLmSXwgypyAFln6qlgaV+a6H1RaTBrpF12ciuY+bna
8 | 9ewBXbAdM2wYPBxq8ifZfl/TngvX8TAqrNwx8prvo3EwbzAOBgNVHQ8BAf8EBAMC
9 | BsAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMB0GA1UdDgQWBBSaOetP
10 | WqlSUA8kI4USxm7Q8AuFRTAfBgNVHSMEGDAWgBSR09em+Xt3/Hldy9IyrLtABLD4
11 | /zAKBggqgRzPVQGDdQNIADBFAiAWE82lXaNtLlNOLAluzlJUpUnodpDQ121tgX5f
12 | ZnKVwQIhAKpId+6AumorqW0QQcgaPrwP3OyJed1XPLxvOYkMmSdT
13 | -----END CERTIFICATE-----
14 |
--------------------------------------------------------------------------------
/pkcs12/errors.go:
--------------------------------------------------------------------------------
1 | // Copyright 2015 The Go Authors. All rights reserved.
2 | // Use of this source code is governed by a BSD-style
3 | // license that can be found in the LICENSE file.
4 |
5 | package pkcs12
6 |
7 | import "errors"
8 |
9 | var (
10 | // ErrDecryption represents a failure to decrypt the input.
11 | ErrDecryption = errors.New("go-pkcs12: decryption error, incorrect padding")
12 |
13 | // ErrIncorrectPassword is returned when an incorrect password is detected.
14 | // Usually, P12/PFX data is signed to be able to verify the password.
15 | ErrIncorrectPassword = errors.New("go-pkcs12: decryption password incorrect")
16 | )
17 |
18 | // NotImplementedError indicates that the input is not currently supported.
19 | type NotImplementedError string
20 |
21 | func (e NotImplementedError) Error() string {
22 | return "go-pkcs12: " + string(e)
23 | }
24 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | sudo: false
2 | dist: bionic
3 | language: go
4 | os:
5 | - linux
6 | - osx
7 | osx_image: xcode11
8 | go:
9 | - 1.14.x
10 | - 1.15.x
11 | before_install:
12 | - export GO111MODULE=on
13 | install:
14 | - go get -u golang.org/x/lint/golint
15 | - export golint=$(go list -f {{.Target}} golang.org/x/lint/golint)
16 | - export GODEBUG=x509ignoreCN=0
17 | - go mod vendor
18 | - go build -v ./sm2
19 | - go build -v ./sm3
20 | - go build -v ./sm4
21 | - go build -v ./x509
22 | - go build -v ./pkcs12
23 | - go build -v ./gmtls/gmcredentials
24 | - go build -v ./gmtls/gmcredentials/echo
25 | - go build -v ./gmtls/websvr
26 | script:
27 | - go vet ./sm2
28 | - go vet ./sm3
29 | - go vet ./sm4
30 | - go vet ./x509
31 | - go vet ./pkcs12
32 | - go vet ./gmtls/gmcredentials
33 | - go vet ./gmtls/websvr
34 | - golint .
35 | - go test -v ./...
36 |
--------------------------------------------------------------------------------
/gmtls/gmcredentials/testdata/user.cert:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | MIICVDCCAfugAwIBAgICEAAwCgYIKoEcz1UBg3UwTTELMAkGA1UEBhMCQ04xEjAQ
3 | BgNVBAgMCVNoYW5nIEhhaTEUMBIGA1UECgwLZXhhbXBsZS5jb20xFDASBgNVBAMM
4 | C2V4YW1wbGUuY29tMB4XDTIwMTAyNjE0MjcyOVoXDTIxMTAyNjE0MjcyOVowUjEL
5 | MAkGA1UEBhMCQ04xEjAQBgNVBAgMCVNoYW5nIEhhaTEUMBIGA1UECgwLZXhhbXBs
6 | ZS5jb20xGTAXBgNVBAMMEHRlc3QuZXhhbXBsZS5jb20wWTATBgcqhkjOPQIBBggq
7 | gRzPVQGCLQNCAATonWvfNyA4L44dhOmXXNuATGnlwwFbtxoNVms+FiIw7yP5NEkH
8 | mbhMAjiANvrx3W3BhTtXmdYWclMKzr6xwd54o4HFMIHCMAkGA1UdEwQCMAAwEQYJ
9 | YIZIAYb4QgEBBAQDAgWgMDMGCWCGSAGG+EIBDQQmFiRPcGVuU1NMIEdlbmVyYXRl
10 | ZCBDbGllbnQgQ2VydGlmaWNhdGUwHQYDVR0OBBYEFPi+UWQ/MQI3R9BR7qAKVMcu
11 | /W+hMB8GA1UdIwQYMBaAFHjvVIix6xnL8H3Zbo1tZ6uKgRytMA4GA1UdDwEB/wQE
12 | AwIF4DAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwQwCgYIKoEcz1UBg3UD
13 | RwAwRAIgegBDw4lqQIIcfe20R8j+B7i9BtQx9vSDjL47nNRAbmoCIFipPgm0FyHK
14 | Xh2FFAQA4TfDK+geQYdUTDtR6AnCDZST
15 | -----END CERTIFICATE-----
16 |
--------------------------------------------------------------------------------
/azure-pipelines.yml:
--------------------------------------------------------------------------------
1 | pool:
2 | vmImage: 'ubuntu-18.04'
3 |
4 | strategy:
5 | matrix:
6 | LTS:
7 | goVersion: '1.15'
8 | latest:
9 | goVersion: '1.14'
10 |
11 | steps:
12 | - task: GoTool@0
13 | inputs:
14 | version: $(goVersion)
15 | - script: export GODEBUG=x509ignoreCN=0
16 | - script: go build -v ./sm2
17 | - script: go build -v ./sm3
18 | - script: go build -v ./sm4
19 | - script: go build -v ./x509
20 | - script: go build -v ./pkcs12
21 | - script: go build -v ./gmtls/gmcredentials
22 | - script: go build -v ./gmtls/gmcredentials/echo
23 | - script: go build -v ./gmtls/websvr
24 | - script: go mod vendor
25 | - script: go vet ./sm2
26 | - script: go vet ./sm3
27 | - script: go vet ./sm4
28 | - script: go vet ./x509
29 | - script: go vet ./pkcs12
30 | - script: go vet ./gmtls/gmcredentials
31 | - script: go vet ./gmtls/websvr
32 | - script: go test -v ./...
33 | displayName: go test recursive
34 |
35 |
--------------------------------------------------------------------------------
/gmtls/auto_switch_config.go:
--------------------------------------------------------------------------------
1 | package gmtls
2 |
3 | // NewBasicAutoSwitchConfig 返回一个实现了GMSSL/TLS自动切换的配置
4 | //
5 | // sm2SigCert: SM2 签名密钥对、证书
6 | // sm2EncCert: SM2 加密密钥对、证书
7 | // stdCert: RSA/ECC 标准的密钥对、证书
8 | //
9 | // return: 最基础的Config对象
10 | func NewBasicAutoSwitchConfig(sm2SigCert, sm2EncCert, stdCert *Certificate) (*Config, error) {
11 | fncGetSignCertKeypair := func(info *ClientHelloInfo) (*Certificate, error) {
12 | gmFlag := false
13 | // 检查支持协议中是否包含GMSSL
14 | for _, v := range info.SupportedVersions {
15 | if v == VersionGMSSL {
16 | gmFlag = true
17 | break
18 | }
19 | }
20 |
21 | if gmFlag {
22 | return sm2SigCert, nil
23 | } else {
24 | return stdCert, nil
25 | }
26 | }
27 |
28 | fncGetEncCertKeypair := func(info *ClientHelloInfo) (*Certificate, error) {
29 | return sm2EncCert, nil
30 | }
31 | support := NewGMSupport()
32 | support.EnableMixMode()
33 | return &Config{
34 | GMSupport: support,
35 | GetCertificate: fncGetSignCertKeypair,
36 | GetKECertificate: fncGetEncCertKeypair,
37 | }, nil
38 | }
39 |
--------------------------------------------------------------------------------
/gmtls/gmcredentials/testdata/encrypt.cert:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | MIICqzCCAlGgAwIBAgICEAAwCgYIKoEcz1UBg3UwTTELMAkGA1UEBhMCQ04xEjAQ
3 | BgNVBAgMCVNoYW5nIEhhaTEUMBIGA1UECgwLZXhhbXBsZS5jb20xFDASBgNVBAMM
4 | C2V4YW1wbGUuY29tMB4XDTIwMTAyNjE0MjcyOVoXDTIxMTAyNjE0MjcyOVowUjEL
5 | MAkGA1UEBhMCQ04xEjAQBgNVBAgMCVNoYW5nIEhhaTEUMBIGA1UECgwLZXhhbXBs
6 | ZS5jb20xGTAXBgNVBAMMEHRlc3QuZXhhbXBsZS5jb20wWTATBgcqhkjOPQIBBggq
7 | gRzPVQGCLQNCAAT/RTpRPyZ2AqaNl3EO+YzgGf51lriYqhwp7OfDD+SF5jUquSao
8 | C2L51zbH9FtCRkGMJW0+kBerZ17d86h7cxlMo4IBGjCCARYwCQYDVR0TBAIwADAR
9 | BglghkgBhvhCAQEEBAMCBkAwMwYJYIZIAYb4QgENBCYWJE9wZW5TU0wgR2VuZXJh
10 | dGVkIFNlcnZlciBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUCVs5pTt4j4EAvDwwqoEE
11 | mU4GjhMwfQYDVR0jBHYwdIAUeO9UiLHrGcvwfdlujW1nq4qBHK2hUaRPME0xCzAJ
12 | BgNVBAYTAkNOMRIwEAYDVQQIDAlTaGFuZyBIYWkxFDASBgNVBAoMC2V4YW1wbGUu
13 | Y29tMRQwEgYDVQQDDAtleGFtcGxlLmNvbYIJAMQooIBlaTnvMA4GA1UdDwEB/wQE
14 | AwIFIDATBgNVHSUEDDAKBggrBgEFBQcDATAKBggqgRzPVQGDdQNIADBFAiA+3xzT
15 | MFqyKrdPcBVxOPHc/db5uAEIvRZUDYmjxWnbkAIhALOGXm49WI2X4PpOYPhQGiwp
16 | LKG+pd6+7i925lHNY5A9
17 | -----END CERTIFICATE-----
18 |
--------------------------------------------------------------------------------
/gmtls/gmcredentials/testdata/sign.cert:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | MIICqjCCAlGgAwIBAgICEAAwCgYIKoEcz1UBg3UwTTELMAkGA1UEBhMCQ04xEjAQ
3 | BgNVBAgMCVNoYW5nIEhhaTEUMBIGA1UECgwLZXhhbXBsZS5jb20xFDASBgNVBAMM
4 | C2V4YW1wbGUuY29tMB4XDTIwMTAyNjE0MjcyOVoXDTIxMTAyNjE0MjcyOVowUjEL
5 | MAkGA1UEBhMCQ04xEjAQBgNVBAgMCVNoYW5nIEhhaTEUMBIGA1UECgwLZXhhbXBs
6 | ZS5jb20xGTAXBgNVBAMMEHRlc3QuZXhhbXBsZS5jb20wWTATBgcqhkjOPQIBBggq
7 | gRzPVQGCLQNCAASqGDkM9U2uwvaRceBzqFmtQTLmhQaWsGtA6QBD4jlZ0Vog13HV
8 | HEhTXbnaJYsfVjoxIK0ZGdKIgzK7gSUbVeLpo4IBGjCCARYwCQYDVR0TBAIwADAR
9 | BglghkgBhvhCAQEEBAMCBkAwMwYJYIZIAYb4QgENBCYWJE9wZW5TU0wgR2VuZXJh
10 | dGVkIFNlcnZlciBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUWewLKGmXW5FINNqKnq8b
11 | svOsjpYwfQYDVR0jBHYwdIAUeO9UiLHrGcvwfdlujW1nq4qBHK2hUaRPME0xCzAJ
12 | BgNVBAYTAkNOMRIwEAYDVQQIDAlTaGFuZyBIYWkxFDASBgNVBAoMC2V4YW1wbGUu
13 | Y29tMRQwEgYDVQQDDAtleGFtcGxlLmNvbYIJAMQooIBlaTnvMA4GA1UdDwEB/wQE
14 | AwIHgDATBgNVHSUEDDAKBggrBgEFBQcDATAKBggqgRzPVQGDdQNHADBEAiBnw6BM
15 | xCGIvFFuL3i+iYbNZbAhPiTb1kB4ZLJ3O3JumAIgXA2Rux0dW3r0FS8i+IS0CGDg
16 | fVOqRCWlxZBhMJvPeIk=
17 | -----END CERTIFICATE-----
18 |
--------------------------------------------------------------------------------
/gmtls/gmcredentials/credentials_util_go18.go:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright Suzhou Tongji Fintech Research Institute 2017 All Rights Reserved.
3 | Licensed under the Apache License, Version 2.0 (the "License");
4 | you may not use this file except in compliance with the License.
5 | You may obtain a copy of the License at
6 |
7 | http://www.apache.org/licenses/LICENSE-2.0
8 |
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
14 | */
15 |
16 | package gmcredentials
17 |
18 | import gmtls "github.com/tjfoc/gmsm/gmtls"
19 |
20 | // cloneTLSConfig returns a shallow clone of the exported
21 | // fields of cfg, ignoring the unexported sync.Once, which
22 | // contains a mutex and must not be copied.
23 | //
24 | // If cfg is nil, a new zero tls.Config is returned.
25 | func cloneTLSConfig(cfg *gmtls.Config) *gmtls.Config {
26 | if cfg == nil {
27 | return &gmtls.Config{}
28 | }
29 |
30 | return cfg.Clone()
31 | }
32 |
--------------------------------------------------------------------------------
/sm4/padding/bloc_cryptor_test.go:
--------------------------------------------------------------------------------
1 | package padding
2 |
3 | import (
4 | "bytes"
5 | "crypto/cipher"
6 | "crypto/rand"
7 | "fmt"
8 | "github.com/tjfoc/gmsm/sm4"
9 | "testing"
10 | )
11 |
12 | func TestP7BlockDecrypt(t *testing.T) {
13 | src := bytes.Repeat([]byte{7}, 16)
14 |
15 | srcIn := bytes.NewBuffer(src)
16 | encOut := bytes.NewBuffer(make([]byte, 0, 1024))
17 |
18 | key := make([]byte, 16)
19 | iv := make([]byte, 16)
20 | _, _ = rand.Read(key)
21 | _, _ = rand.Read(iv)
22 | fmt.Printf("key: %02X\n", key)
23 | fmt.Printf("iv : %02X\n", iv)
24 | block, err := sm4.NewCipher(key)
25 | if err != nil {
26 | t.Fatal(err)
27 | }
28 | encrypter := cipher.NewCBCEncrypter(block, iv)
29 |
30 | err = P7BlockEnc(encrypter, srcIn, encOut)
31 | if err != nil {
32 | t.Fatal(err)
33 | }
34 | fmt.Printf("原文: %02X\n", src)
35 | fmt.Printf("加密: %02X\n", encOut.Bytes())
36 |
37 | decrypter := cipher.NewCBCDecrypter(block, iv)
38 | decOut := bytes.NewBuffer(make([]byte, 0, 1024))
39 | err = P7BlockDecrypt(decrypter, encOut, decOut)
40 | if err != nil {
41 | t.Fatal(err)
42 | }
43 |
44 | fmt.Printf("解密: %02X\n", decOut.Bytes())
45 | if !bytes.Equal(src, decOut.Bytes()) {
46 | t.Fatalf("实际解密结果: %02X, 期待结果: %02X", decOut.Bytes(), src)
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/gmtls/websvr/certs/rsa_auth_cert.cer:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | MIIDUTCCAjmgAwIBAgIIAs4GXZbE1BcwDQYJKoZIhvcNAQELBQAwQjELMAkGA1UE
3 | BhMCQ04xDzANBgNVBAgMBua1meaxnzEPMA0GA1UEBwwG5p2t5beeMREwDwYDVQQK
4 | DAjmtYvor5VDQTAeFw0yMTA2MDMxNTA5NDVaFw0zMTA1MzAwNjU0NThaMDsxCzAJ
5 | BgNVBAYTAkNOMQ8wDQYDVQQIDAbmtZnmsZ8xDzANBgNVBAcMBuadreW3njEKMAgG
6 | A1UEAwwBKjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOk2VvN/B+UU
7 | voDdmxVZTA6ZQH/BZfDyACj3ssVCbNGwZllnjbb5GoLBA+3apQ6GNY5p5lzZoAI+
8 | CR907g9Bjk4f9so9Nz97yDu4kGzFPfWQEqWAb3R/HA/IpXSyLWcCXcrYPbp8cFbT
9 | xMItDDO9RpwJ44u/npdk5TagiUJL/UdH3hDv9Ic8SvncDB45SP37aNzVrNjKi6Pe
10 | ZbDNSh2wVumW5Lvw+rKFLDKIRVnIAzisQrVrenDEDXHawV42J3FEjQ2q8ZIwVGzH
11 | WBfi4Pn6k3yd9GAg1HMCwapkoPNNcubAIo07YgcHJMSbAKIBG2p/RKBs3PsVrBxi
12 | e77iy5jTRp0CAwEAAaNSMFAwDgYDVR0PAQH/BAQDAgP4MB0GA1UdJQQWMBQGCCsG
13 | AQUFBwMBBggrBgEFBQcDAjAfBgNVHSMEGDAWgBTkg8zWkAOryxH1WmniX1Pc7zfk
14 | qTANBgkqhkiG9w0BAQsFAAOCAQEAgyoKfu6L3kaevwYb1LhlaUelSRLim6MTID3F
15 | +hxUF+LhORYSmZP92+YTIX7DZeWaXYfo14UTB9nVr5a27hz1M0GHRnI1aq/NeNiz
16 | jQNvRJmY6qgVyFCPCnanhqx3hHopU0ys4DXKnj4BJXmHvYeg8Ilq/ZYPY8Kiab0Q
17 | P7oOBsa68fY7/8mh8V1uo0FnfxupeCGsnA4V+xJ8d3EperhNoPlon8JlUyJMvITx
18 | /WJCH+ZeB+8OuUiK/XPATDrwdF3Ccwpm5CqzxRiLzZrygQF/b2QQ9B4VisY5DkAQ
19 | aXq5MlJxvF8DYmDb6EkvR5XwahElvYBX58Y/Ry+CtUwHkYt8qA==
20 | -----END CERTIFICATE-----
21 |
--------------------------------------------------------------------------------
/gmtls/websvr/certs/RSA_CA.cer:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | MIIDaTCCAlGgAwIBAgIIAs4Fs2xsiCcwDQYJKoZIhvcNAQELBQAwQjELMAkGA1UE
3 | BhMCQ04xDzANBgNVBAgMBua1meaxnzEPMA0GA1UEBwwG5p2t5beeMREwDwYDVQQK
4 | DAjmtYvor5VDQTAeFw0yMTA1MzAwNjU0NThaFw0zMTA1MzAwNjU0NThaMEIxCzAJ
5 | BgNVBAYTAkNOMQ8wDQYDVQQIDAbmtZnmsZ8xDzANBgNVBAcMBuadreW3njERMA8G
6 | A1UECgwI5rWL6K+VQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDM
7 | iY3CcuyLC1Bh1weSpubbi6L7D7dFR1o8iynhC/bTVUvbM9zpTMU/54t9QiZo+aIQ
8 | 5q2wRwppW10eBL2WKYFNo6W9LcSqoDUSiiux8RXtU8EPGcJHbOQPcym7RZ1Q8StG
9 | bauXPVgbvuP7r3Q9QMVrQSDrN2Ek+D88mCqCwokSaRe0Ii6V7Sntx1De+geLAk3r
10 | gHUdanddLnfb2PEFOpnBoWStUJH5HnxDMaBxqN3P7JMmZmTHrcUr0wodKJTlHEr6
11 | DLBjP62K4u1Yoh5HD8+RRUVFfb7aXHetgReP5zAkmUhtY00n3KLF3g4UFcNxf1Lt
12 | snf/Va1WK6P+tReFG+jvAgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMB
13 | Af8EBTADAQH/MB0GA1UdDgQWBBTkg8zWkAOryxH1WmniX1Pc7zfkqTAfBgNVHSME
14 | GDAWgBTkg8zWkAOryxH1WmniX1Pc7zfkqTANBgkqhkiG9w0BAQsFAAOCAQEAxrxf
15 | mkWhMk0WikudPfQMmx3VIN0itxLMAeaV/56txMVu601hptcK76dgoVVMD4UWyaAI
16 | 8SZtLk+CpTSKGKBWbwkuop6E0kv9Ush2j5+cG8qj5AETsiwmUCUm/+YzuDqVXrgE
17 | cLLLYiF6r+p8/HM0+3l5uVw3bNLcUlZdUdIKsHhtfuytAGYz/DQnkgOCbgOx+j4k
18 | MRKK4iR+VWXYLksL0YleYD+JCd5HOTDEUnXjry0lqEAka4V0HMAHqv1+yxOzr/N6
19 | AUIy6TJfzTV1IFTv0BcFCq5DDzzK9Tzvmvbktb/XdPbi5dR53yCzITlBR4MXr5sy
20 | nggpRf1TWY7rlIw7GQ==
21 | -----END CERTIFICATE-----
22 |
--------------------------------------------------------------------------------
/gmtls/websvr/certs/rsa_sign.cer:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | MIIDcDCCAligAwIBAgIIAs4Fs3BZK6cwDQYJKoZIhvcNAQELBQAwQjELMAkGA1UE
3 | BhMCQ04xDzANBgNVBAgMBua1meaxnzEPMA0GA1UEBwwG5p2t5beeMREwDwYDVQQK
4 | DAjmtYvor5VDQTAeFw0yMTA1MzAwNzIwNDJaFw0zMTA1MzAwNjU0NThaMFoxCzAJ
5 | BgNVBAYTAkNOMQ8wDQYDVQQIDAbmtZnmsZ8xDzANBgNVBAcMBuadreW3njEVMBMG
6 | A1UECgwM5rWL6K+V5YWs5Y+4MRIwEAYDVQQDEwlsb2NhbGhvc3QwggEiMA0GCSqG
7 | SIb3DQEBAQUAA4IBDwAwggEKAoIBAQC/FGo2/jbU3k5Ua+MkCkgcUvdQJMjg2dw/
8 | zja0znHiGUlyfg2wWv9W5bXrgRGBAbSeGKSiMgePK43xpBGwoWM0TdqAOxQOqpQO
9 | wCgxShstsLz+3R2az0dza3wuVGlz9Pn/maSUBrrQuzyDwoY6XhQYHERfbvMzHQ2K
10 | ye02hdIdBGbgA7VtUJUAWlvjentIknUK+C3EKKOz0XgpGCVaud9U0t2QK3zpRTMW
11 | klJcIXHYUq7UUFBEq7gn3GPbzRe5LDp1sgYgemz1caRgUnTRL00R8jKqUUqvHdOW
12 | jrYk9c4vNmNZeVLnNpWNXM8/SY3RLXOhS1ncrJK33VFJsZPjBqLLAgMBAAGjUjBQ
13 | MA4GA1UdDwEB/wQEAwID+DAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIw
14 | HwYDVR0jBBgwFoAU5IPM1pADq8sR9Vpp4l9T3O835KkwDQYJKoZIhvcNAQELBQAD
15 | ggEBAIleQQd1YgNS/+7gCJYsTi1VGqsUKpCShSe+DFUbOnJgKaGNAcVERZkYspz4
16 | k9dxcM0IOabxtQWNj/5sfeIwzar0btMo8J4myrgM9iT3f7LXCIUx6cSFZimlZ0JX
17 | PS9FEd/8/YhPhDuo7r0GK9OBqe+77sa7jhYLHZyhmtsDGONjivANpZbLu4t2GHjh
18 | 300adouQF6zYMkg+49lrSf7QLqgEE5JJM8CkbaY3O7FflS7kEHCzCd/cfqKacvWb
19 | 4Kl0T4TezbWbwLUY1pY8Ik9aHVsghm0tUb6e1QD5cDcN7EyhSnFug1TcG6YbhyZC
20 | lwciqUnSvOPYbVlosRFmQ2kUp9U=
21 | -----END CERTIFICATE-----
22 |
--------------------------------------------------------------------------------
/sm4/padding/bloc_cryptor.go:
--------------------------------------------------------------------------------
1 | package padding
2 |
3 | import (
4 | "crypto/cipher"
5 | "io"
6 | )
7 |
8 | // P7BlockDecrypt 解密密文,并去除PKCS#7填充
9 | // decrypter: 块解密器
10 | // in: 密文输入流
11 | // out: 明文输出流
12 | func P7BlockDecrypt(decrypter cipher.BlockMode, in io.Reader, out io.Writer) error {
13 | bufIn := make([]byte, 1024)
14 | bufOut := make([]byte, 1024)
15 | p7Out := NewPKCS7PaddingWriter(out, decrypter.BlockSize())
16 | for {
17 | n, err := in.Read(bufIn)
18 | if err != nil && err != io.EOF {
19 | return err
20 | }
21 | if n == 0 {
22 | break
23 | }
24 | decrypter.CryptBlocks(bufOut, bufIn[:n])
25 | _, err = p7Out.Write(bufOut[:n])
26 | if err != nil {
27 | return err
28 | }
29 | }
30 | return p7Out.Final()
31 | }
32 |
33 | // P7BlockEnc 以PKCS#7填充模式填充原文,并加密输出
34 | // encrypter: 块加密器
35 | // in: 明文输入流
36 | // out: 密文输出流
37 | func P7BlockEnc(encrypter cipher.BlockMode, in io.Reader, out io.Writer) error {
38 | bufIn := make([]byte, 1024)
39 | bufOut := make([]byte, 1024)
40 | p7In := NewPKCS7PaddingReader(in, encrypter.BlockSize())
41 | for {
42 | n, err := p7In.Read(bufIn)
43 | if err != nil && err != io.EOF {
44 | return err
45 | }
46 | if n == 0 {
47 | break
48 | }
49 | encrypter.CryptBlocks(bufOut, bufIn[:n])
50 | _, err = out.Write(bufOut[:n])
51 | if err != nil {
52 | return err
53 | }
54 | }
55 | return nil
56 | }
57 |
--------------------------------------------------------------------------------
/sm2/utils.go:
--------------------------------------------------------------------------------
1 | package sm2
2 |
3 | import (
4 | "encoding/asn1"
5 | "math/big"
6 | )
7 |
8 | func Decompress(a []byte) *PublicKey {
9 | var aa, xx, xx3 sm2P256FieldElement
10 |
11 | P256Sm2()
12 | x := new(big.Int).SetBytes(a[1:])
13 | curve := sm2P256
14 | sm2P256FromBig(&xx, x)
15 | sm2P256Square(&xx3, &xx) // x3 = x ^ 2
16 | sm2P256Mul(&xx3, &xx3, &xx) // x3 = x ^ 2 * x
17 | sm2P256Mul(&aa, &curve.a, &xx) // a = a * x
18 | sm2P256Add(&xx3, &xx3, &aa)
19 | sm2P256Add(&xx3, &xx3, &curve.b)
20 |
21 | y2 := sm2P256ToBig(&xx3)
22 | y := new(big.Int).ModSqrt(y2, sm2P256.P)
23 | if getLastBit(y) != uint(a[0]) {
24 | y.Sub(sm2P256.P, y)
25 | }
26 | return &PublicKey{
27 | Curve: P256Sm2(),
28 | X: x,
29 | Y: y,
30 | }
31 | }
32 |
33 | func Compress(a *PublicKey) []byte {
34 | buf := []byte{}
35 | yp := getLastBit(a.Y)
36 | buf = append(buf, a.X.Bytes()...)
37 | if n := len(a.X.Bytes()); n < 32 {
38 | buf = append(zeroByteSlice()[:(32-n)], buf...)
39 | }
40 | buf = append([]byte{byte(yp)}, buf...)
41 | return buf
42 | }
43 |
44 | type sm2Signature struct {
45 | R, S *big.Int
46 | }
47 |
48 | func SignDigitToSignData(r, s *big.Int) ([]byte, error) {
49 | return asn1.Marshal(sm2Signature{r, s})
50 | }
51 |
52 | func SignDataToSignDigit(sign []byte) (*big.Int, *big.Int, error) {
53 | var sm2Sign sm2Signature
54 |
55 | _, err := asn1.Unmarshal(sign, &sm2Sign)
56 | if err != nil {
57 | return nil, nil, err
58 | }
59 | return sm2Sign.R, sm2Sign.S, nil
60 | }
61 |
--------------------------------------------------------------------------------
/pkcs12/mac.go:
--------------------------------------------------------------------------------
1 | // Copyright 2015 The Go Authors. All rights reserved.
2 | // Use of this source code is governed by a BSD-style
3 | // license that can be found in the LICENSE file.
4 |
5 | package pkcs12
6 |
7 | import (
8 | "crypto/hmac"
9 | "crypto/sha1"
10 | "crypto/x509/pkix"
11 | "encoding/asn1"
12 | )
13 |
14 | type macData struct {
15 | Mac digestInfo
16 | MacSalt []byte
17 | Iterations int `asn1:"optional,default:1"`
18 | }
19 |
20 | // from PKCS#7:
21 | type digestInfo struct {
22 | Algorithm pkix.AlgorithmIdentifier
23 | Digest []byte
24 | }
25 |
26 | var (
27 | oidSHA1 = asn1.ObjectIdentifier([]int{1, 3, 14, 3, 2, 26})
28 | )
29 |
30 | func verifyMac(macData *macData, message, password []byte) error {
31 | if !macData.Mac.Algorithm.Algorithm.Equal(oidSHA1) {
32 | return NotImplementedError("unknown digest algorithm: " + macData.Mac.Algorithm.Algorithm.String())
33 | }
34 |
35 | key := pbkdf(sha1Sum, 20, 64, macData.MacSalt, password, macData.Iterations, 3, 20)
36 |
37 | mac := hmac.New(sha1.New, key)
38 | mac.Write(message)
39 | expectedMAC := mac.Sum(nil)
40 |
41 | if !hmac.Equal(macData.Mac.Digest, expectedMAC) {
42 | return ErrIncorrectPassword
43 | }
44 | return nil
45 | }
46 |
47 | func computeMac(macData *macData, message, password []byte) error {
48 | if !macData.Mac.Algorithm.Algorithm.Equal(oidSHA1) {
49 | return NotImplementedError("unknown digest algorithm: " + macData.Mac.Algorithm.Algorithm.String())
50 | }
51 |
52 | key := pbkdf(sha1Sum, 20, 64, macData.MacSalt, password, macData.Iterations, 3, 20)
53 |
54 | mac := hmac.New(sha1.New, key)
55 | mac.Write(message)
56 | macData.Mac.Digest = mac.Sum(nil)
57 |
58 | return nil
59 | }
60 |
--------------------------------------------------------------------------------
/pkcs12/bmp-string.go:
--------------------------------------------------------------------------------
1 | // Copyright 2015 The Go Authors. All rights reserved.
2 | // Use of this source code is governed by a BSD-style
3 | // license that can be found in the LICENSE file.
4 |
5 | package pkcs12
6 |
7 | import (
8 | "errors"
9 | "unicode/utf16"
10 | )
11 |
12 | // bmpString returns s encoded in UCS-2 with a zero terminator.
13 | func bmpString(s string) ([]byte, error) {
14 | // References:
15 | // https://tools.ietf.org/html/rfc7292#appendix-B.1
16 | // http://en.wikipedia.org/wiki/Plane_(Unicode)#Basic_Multilingual_Plane
17 | // - non-BMP characters are encoded in UTF 16 by using a surrogate pair of 16-bit codes
18 | // EncodeRune returns 0xfffd if the rune does not need special encoding
19 | // - the above RFC provides the info that BMPStrings are NULL terminated.
20 |
21 | ret := make([]byte, 0, 2*len(s)+2)
22 |
23 | for _, r := range s {
24 | if t, _ := utf16.EncodeRune(r); t != 0xfffd {
25 | return nil, errors.New("go-pkcs12: string contains characters that cannot be encoded in UCS-2")
26 | }
27 | ret = append(ret, byte(r/256), byte(r%256))
28 | }
29 |
30 | return append(ret, 0, 0), nil
31 | }
32 |
33 | func decodeBMPString(bmpString []byte) (string, error) {
34 | if len(bmpString)%2 != 0 {
35 | return "", errors.New("go-pkcs12: odd-length BMP string")
36 | }
37 |
38 | // strip terminator if present
39 | if l := len(bmpString); l >= 2 && bmpString[l-1] == 0 && bmpString[l-2] == 0 {
40 | bmpString = bmpString[:l-2]
41 | }
42 |
43 | s := make([]uint16, 0, len(bmpString)/2)
44 | for len(bmpString) > 0 {
45 | s = append(s, uint16(bmpString[0])<<8+uint16(bmpString[1]))
46 | bmpString = bmpString[2:]
47 | }
48 |
49 | return string(utf16.Decode(s)), nil
50 | }
51 |
--------------------------------------------------------------------------------
/sm3/sm3_test.go:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright Suzhou Tongji Fintech Research Institute 2017 All Rights Reserved.
3 | Licensed under the Apache License, Version 2.0 (the "License");
4 | you may not use this file except in compliance with the License.
5 | You may obtain a copy of the License at
6 |
7 | http://www.apache.org/licenses/LICENSE-2.0
8 |
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
14 | */
15 |
16 | package sm3
17 |
18 | import (
19 | "fmt"
20 | "io/ioutil"
21 | "os"
22 | "testing"
23 | )
24 |
25 | func byteToString(b []byte) string {
26 | ret := ""
27 | for i := 0; i < len(b); i++ {
28 | ret += fmt.Sprintf("%02x", b[i])
29 | }
30 | fmt.Println("ret = ", ret)
31 | return ret
32 | }
33 | func TestSm3(t *testing.T) {
34 | msg := []byte("test")
35 | err := ioutil.WriteFile("ifile", msg, os.FileMode(0644)) // 生成测试文件
36 | if err != nil {
37 | t.Fatal(err)
38 | }
39 | msg, err = ioutil.ReadFile("ifile")
40 | if err != nil {
41 | t.Fatal(err)
42 | }
43 | hw := New()
44 | hw.Write(msg)
45 | hash := hw.Sum(nil)
46 | fmt.Println(hash)
47 | fmt.Printf("hash = %d\n", len(hash))
48 | fmt.Printf("%s\n", byteToString(hash))
49 | hash1 := Sm3Sum(msg)
50 | fmt.Println(hash1)
51 | fmt.Printf("%s\n", byteToString(hash1))
52 |
53 | }
54 |
55 | func BenchmarkSm3(t *testing.B) {
56 | t.ReportAllocs()
57 | msg := []byte("test")
58 | hw := New()
59 | for i := 0; i < t.N; i++ {
60 |
61 | hw.Sum(nil)
62 | Sm3Sum(msg)
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/gmtls/websvr/certs/rsa_auth_key.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN PRIVATE KEY-----
2 | MIIEogIBAAKCAQEA6TZW838H5RS+gN2bFVlMDplAf8Fl8PIAKPeyxUJs0bBmWWeN
3 | tvkagsED7dqlDoY1jmnmXNmgAj4JH3TuD0GOTh/2yj03P3vIO7iQbMU99ZASpYBv
4 | dH8cD8ildLItZwJdytg9unxwVtPEwi0MM71GnAnji7+el2TlNqCJQkv9R0feEO/0
5 | hzxK+dwMHjlI/fto3NWs2MqLo95lsM1KHbBW6Zbku/D6soUsMohFWcgDOKxCtWt6
6 | cMQNcdrBXjYncUSNDarxkjBUbMdYF+Lg+fqTfJ30YCDUcwLBqmSg801y5sAijTti
7 | BwckxJsAogEban9EoGzc+xWsHGJ7vuLLmNNGnQIDAQABAoIBAF2ev9cuJrgy1Ksc
8 | yzYNy/eMVBU1STwpmiDYFv8TRGYFP4EijgRnCdp1q6Mfg+VJwVQzdRPPFWnxB26G
9 | XU7ojT0VndfgLT6h7Wb0F55irBXZSXMBFT0aDeTUMn+fS5SvoYFdv6IOdHaWusUM
10 | mnpmwGLBoYQnX339NfrxBUkFAl9LWUrw3Y+ON9R6uEeSMntD84L4R9R+84S5BeTr
11 | 6zb/XoT4YvD6RS8HOB7XBCGlLTwds+a4zyQnuCCHbKIES9lxItF0QbprG5J+Q7gp
12 | lebi/zXLWbUg22S3mzTmP3R8l0LWwKhyPnBh8onNf/Nroa68r9FlEFSglj/5MAvJ
13 | pAD6/80CgYEA975QPGmW6mxBxUr3OVZTKmTVGHonEb/qVr489zgnruWwbY7Y344V
14 | qw2nY+EiT2ftGsZmb/LZ3fEaSdmKYb1rDS9Jslfd3E1yUygFFtwqiGqWEp8LDDvU
15 | UgqDvMdoDaGIKcl0EyeWOjCi073B2MSC9prKY9MuxHpOfZ7f4aN7GbsCgYEA8PwM
16 | zZZCAWRFlasxYe59uU63vSmDGkMcy0W494IrfcqPLIoin4Xkdrjb1LVI6dYb27/W
17 | 2gFMKMlWCHCvaayFzgmwjIK8+r+nUWAuxCWljxOaB3wIKf3q1sNVAITfFTuV1k6d
18 | Svl55fpYAPqDu6JLSqoIZK+Vw2amTOnJSrZoT4cCgYBuZ5uuMIgW1EPDPpNKNBQ/
19 | 8kuc6uL6YAJ4wbK9oYLdyHKFgIFZryIs5prQQgZeSLw7kGsaPKmm5MmIW6/1uso4
20 | R/iZx9qRUNpAALez5k32GTnj9oif3RHTtefbeyn92RyrMqHN33htWjtWDVyT049h
21 | gr3rGrPez3qnNOQk1AwJ/QKBgGeOuOXEE1tLvsdhiNgfx7FRTY4hf7BSdNY5gRID
22 | wzLMUBiAx/4raJFIQVe4C7xJATG+z9JhSlwgoTMBUbAkrl9rNI49RH6wy3Mh1Rb/
23 | YpUIhGGBAHUjI77ks+uELeWO9IXixJ9KdALLQPQys1d3l8lfJjo2ZjJRM1fMA29y
24 | 0YKTAoGAA7adLMc8uePn6Dclw/MQ291t3JWYKOuZ5bM4BfwMf+Xr5XHuIylNaxgJ
25 | JyIkZcrnEpIjKwtwCBUf3fJ2I39d7Euhdss7yS+YVrvuQSINtoKRmZ45PKP0MKNf
26 | +YyctbsNPGmbzK93WBijRefdAIvyGG29FlXwnKP9A0tBXM7yx1o=
27 | -----END PRIVATE KEY-----
28 |
--------------------------------------------------------------------------------
/gmtls/websvr/certs/rsa_sign_key.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN PRIVATE KEY-----
2 | MIIEowIBAAKCAQEAvxRqNv421N5OVGvjJApIHFL3UCTI4NncP842tM5x4hlJcn4N
3 | sFr/VuW164ERgQG0nhikojIHjyuN8aQRsKFjNE3agDsUDqqUDsAoMUobLbC8/t0d
4 | ms9Hc2t8LlRpc/T5/5mklAa60Ls8g8KGOl4UGBxEX27zMx0NisntNoXSHQRm4AO1
5 | bVCVAFpb43p7SJJ1CvgtxCijs9F4KRglWrnfVNLdkCt86UUzFpJSXCFx2FKu1FBQ
6 | RKu4J9xj280XuSw6dbIGIHps9XGkYFJ00S9NEfIyqlFKrx3Tlo62JPXOLzZjWXlS
7 | 5zaVjVzPP0mN0S1zoUtZ3KySt91RSbGT4waiywIDAQABAoIBAHON1AH30I8A9ZvG
8 | NvHnqd4/KkL0S+r2tWR8v8auBl72bd1ob7zT+xDBEDggsMY0ktb9DirsWHfznf6g
9 | +vW3U7gg0N+1WpbX/3vAJ05Pg4opFNKIQ8wISCx7tviJodA3OSyi7M18GGP8p0cD
10 | T4tis4I1LgAMp9SkYDkrjmHnob5biilhdAGseJWjyKMxBc1sqMQVy+Gia49guU0J
11 | fnEOu1jT6P/ZB7P7wyiFEVJKYvU/iMQ2rCiBlBKmAa4ZuV/rMLs7/twwiD1EtMNc
12 | bpwoNeEI7XC+HCwpYNecscIxhs3zcjqasc93B7Sn0MHhdxz2aU6TH2BSA+S1zfzm
13 | +fcgS1kCgYEA/Tl3WERs2VjNW01c5yQ5fz3yKhqHgBZ9KODasLdX4/4b18ZRiQdI
14 | VRCMSjhp0IryYgkH78X6fKIdzA276MNpAK3mcCu6dI6d8ige55A4cwyS3P23b2Ft
15 | VB9TAHUJ+5F3fXHAjXYBzMsDNCkZqedPRj18+GMyHfMV05eqzEzR/p8CgYEAwSyS
16 | 9NDir1lQVcjDy4IF8cjsuFT3R1KbUy29MOCBcTd4RaB/vTEs4nCZlpb9wBBJqQBu
17 | 5CCH5wOxc+WvoEicpzrcwqWBTmUngulVHumub8VeahTHZsbPXDlc6hXg+kXimo0S
18 | rNGHGz76aBEgxpD8KnoRiBXL5KUXkYVSeFtT6FUCgYBlwRTbDEvtHskOekztuNm9
19 | 7seD8bsnVmIe7hQS1OnlfPP1RgT3mkyPmiG1pWun2F3D1TsyN40LTh3JJG+w/e0Q
20 | z9B8nKXFNpXze/nHNWXpnVDaqr1ubWkAV8IDugQz6eVpLC+i6Juajq2P5UAhzQhH
21 | AmhYa4v1CvxnVVfV1ry/owKBgHJrFnhPqZU3D7BgBCjsUN0Pp7bfDMCAG2Q/OUpU
22 | EBehRWnoUQEcuXs+OprJwG8ctqSVjxksc5LPyzHcoBQOLkuXP99C7L4kiCywTCzN
23 | OPcXLn8i46DqrTPw/ing36sd7cShPqiCSsZGnUc6rfEvO01llDDIyEYby0P0dg63
24 | +ZEpAoGBAPQQY2ojWp8smOpQhtkqPjeDb2rjSGoniBz3mapFv4WuPmpQhRKh/dcu
25 | gCIHmXOAEz8nLCKWF+CsKpvLIuO+nyT2XadPuz3nAJM6VwVZ+wrQUEI6tP4DcfqB
26 | SDcVFeEKFw+nZGMFfTm3g5/eFraRjSBK5a5immGBMJCQQanniN7B
27 | -----END PRIVATE KEY-----
28 |
--------------------------------------------------------------------------------
/gmtls/websvr/certs/RSA_CA_KEY.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN PRIVATE KEY-----
2 | MIIEpAIBAAKCAQEAzImNwnLsiwtQYdcHkqbm24ui+w+3RUdaPIsp4Qv201VL2zPc
3 | 6UzFP+eLfUImaPmiEOatsEcKaVtdHgS9limBTaOlvS3EqqA1EoorsfEV7VPBDxnC
4 | R2zkD3Mpu0WdUPErRm2rlz1YG77j+690PUDFa0Eg6zdhJPg/PJgqgsKJEmkXtCIu
5 | le0p7cdQ3voHiwJN64B1HWp3XS5329jxBTqZwaFkrVCR+R58QzGgcajdz+yTJmZk
6 | x63FK9MKHSiU5RxK+gywYz+tiuLtWKIeRw/PkUVFRX2+2lx3rYEXj+cwJJlIbWNN
7 | J9yixd4OFBXDcX9S7bJ3/1WtViuj/rUXhRvo7wIDAQABAoIBAEJngiOYJh26TZ2G
8 | L0o4b4jlm8NAxfJzCOPRFoae2MKh1Z/UBaukpgFqTgobmNbJ/QjZq5goaEPuSpv9
9 | VAPVc8peD+gMXOY8Xx6mxyrdJ45Ge85IQZ/oxV4SuIC5SCrIMZGK94OBggJ4BhJn
10 | Uyizx6Rbn7Fd6GcVRYqJqHuNZu0XprculGZ58CA//EJejDm0QZc8lqFlis5WCJ/G
11 | GMV1xMNx/QhU7ObbzVGfIUeDyYCsO7F3SxWbo9cyToQi/14MeI/kLhSp9CPv2PSL
12 | ezkSazVrRxNqOJBzlTncA+z0p+RLdfvkNB82CAtJdnN94VF5H1/dePkn4HhT9hz5
13 | vP55HZECgYEA8QNqw7qwH6jfRpaAcJ8DP8MPzZVPF7rliK4buQDcE/5LzIP/5BhK
14 | dCT+vKYHcPGF3IqsQ6rZDZ4aUvlzdXi8yolz6NNDgEGYYiQH0qNFY1DnR+YnqtuS
15 | o1+LmZXJkuRk/6w2/Fd+EDK+7SLLQLKDGb+bmReDvW3vye2DbN/mSicCgYEA2UF9
16 | wRA45+2gaK4cEkrovq6j6U8+IYPuQFXVFVKhILGN69/l1ZLamVMGX5tMUwfwJdh8
17 | 2Ewqz5tpdBrrCwdnhQHugZl9YFzLej98eLREOqiOcqAvFVjFsbtfe4jwFn7ciHuO
18 | Fe//xWrI9dVQLhL/cAuJMtTlWVCnAGCIhjj+j/kCgYEAsSVb0eVkEsEi61UvrpeR
19 | 4cnT0b2O1thOYbnnMoHJQQDGYdobuWGJR/jxK2O1UHSVeVaL62imBPZSTu5+yLcn
20 | vI5vHZA6qwiLoobtIQtUsv0CIbyvJ0wgaeiOSSLpeAhbm/jOqYb9Z5aE8vOCBVmw
21 | Nrq4+TtpX1Bw0TC8Ssf/Ej0CgYAnbA7ZnYv16dSVqiJF33nkP+RWTZ7EjiAJZInJ
22 | 2LiMKivKhVI7Mu6fq8UYTCHJX0NgWqwsw4VxLo4wF0JXOfy60eLpeWSau7vgbuyz
23 | KmLHEhbnDdH9WaJl4c4tqGeIbXSu/1yE9ou+0uWsVgy6j4/yUOWQZ7lGP7BODTY4
24 | xNbMYQKBgQCn3AhkE2di4XHdKZOr3aSW6yJovZl+7bF1/xiMuOh5Noz7h6RwVGa4
25 | 2ZJnRyyV3oeOIftkBNls42LPpqo1O2Y7vOdxLtdh9DLJbVAUgobvIufpJ6VSUhmP
26 | THNdL0/ciJ3vP9zLtcVVYR/2IyI+lMbnyhD8BNvFzbblK1NUSJiStQ==
27 | -----END PRIVATE KEY-----
28 |
--------------------------------------------------------------------------------
/sm4/padding/pkcs7_padding_io_test.go:
--------------------------------------------------------------------------------
1 | package padding
2 |
3 | import (
4 | "bytes"
5 | "io"
6 | "testing"
7 | )
8 |
9 | // 测试P7填充Reader
10 | func TestPaddingFileReader_Read(t *testing.T) {
11 | srcIn := bytes.NewBuffer(bytes.Repeat([]byte{'A'}, 16))
12 | p := NewPKCS7PaddingReader(srcIn, 16)
13 |
14 | tests := []struct {
15 | name string
16 | buf []byte
17 | want int
18 | wantErr error
19 | }{
20 | {"读取文件 1B", make([]byte, 1), 1, nil},
21 | {"交叉读取 15B 文件 1B", make([]byte, 16), 16, nil},
22 | {"填充读取 3B", make([]byte, 3), 3, nil},
23 | {"超过填充读取 16B", make([]byte, 16), 12, nil},
24 | {"文件结束 16B", make([]byte, 16), 0, io.EOF},
25 | }
26 | for _, tt := range tests {
27 | t.Run(tt.name, func(t *testing.T) {
28 | got, err := p.Read(tt.buf)
29 | if err != tt.wantErr {
30 | t.Errorf("Read() error = %v, wantErr %v", err, tt.wantErr)
31 | return
32 | }
33 | if got != tt.want {
34 | t.Errorf("Read() 读取到了 = %v, 但是需要 %v", got, tt.want)
35 | }
36 | })
37 | }
38 | }
39 |
40 | // 测试P7填充Writer
41 | func TestPKCS7PaddingWriter_Write(t *testing.T) {
42 | src := []byte{
43 | 0, 1, 2, 3, 4, 5, 6, 7,
44 | }
45 | paddedSrc := append(src, bytes.Repeat([]byte{0x08}, 8)...)
46 | reader := bytes.NewReader(paddedSrc)
47 | out := bytes.NewBuffer(make([]byte, 0, 64))
48 | writer := NewPKCS7PaddingWriter(out, 8)
49 |
50 | for {
51 | buf := make([]byte, 3)
52 | n, err := reader.Read(buf)
53 | if err != nil && err != io.EOF {
54 | t.Fatal(err)
55 | }
56 | if n == 0 {
57 | break
58 | }
59 | _, err = writer.Write(buf[:n])
60 | if err != nil {
61 | t.Fatal(err)
62 | }
63 | }
64 | err := writer.Final()
65 | if err != nil {
66 | t.Fatal(err)
67 | }
68 |
69 | if !bytes.Equal(out.Bytes(), src) {
70 | t.Fatalf("去除填充后实际为 %02X,期待去除填充之后的结果为 %02X", out.Bytes(), src)
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 | # gmsm
3 | GM SM2/3/4 library based on Golang
4 | =======
5 |
6 | [](https://travis-ci.com/github/tjfoc/gmsm)
7 |
8 |
9 | ## Feature
10 | gmsm包含以下主要功能
11 |
12 | SM2: 国密椭圆曲线算法库
13 | . 支持Generate Key, Sign, Verify基础操作
14 | . 支持加密和不加密的pem文件格式(加密方法参见RFC5958, 具体实现参加代码)
15 | . 支持证书的生成,证书的读写(接口兼容rsa和ecdsa的证书)
16 | . 支持证书链的操作(接口兼容rsa和ecdsa)
17 | . 支持crypto.Signer接口
18 |
19 | SM3: 国密hash算法库
20 | . 支持基础的sm3Sum操作
21 | . 支持hash.Hash接口
22 |
23 | SM4: 国密分组密码算法库
24 | . 支持Generate Key, Encrypt, Decrypt基础操作
25 | . 提供Cipher.Block接口
26 | . 支持加密和不加密的pem文件格式(加密方法为pem block加密, 具体函数为x509.EncryptPEMBlock)
27 |
28 | ## [Usage 使用说明](./API使用说明.md)
29 |
30 | ## Communication
31 | tjfoc国密交流
32 |
33 | [](https://gitter.im/tjfoc/gmsm?utm_source=badge&utm_medium=badge&utm_campaign=-badge&utm_content=badge)
34 |
35 |
36 | - 如果你对国密算法开源技术及应用感兴趣,欢迎添加“苏州同济区块链研究院·小助手“微信,回复“国密算法进群”,加入“同济区块链国密算法交流群”。微信二维码如下:
37 | 
38 |
39 | - 发送邮件到tj@wutongchain.com
40 |
41 |
42 | ## License
43 | 版权所有 苏州同济区块链研究院有限公司(http://www.wutongchain.com/)
44 |
45 | Copyright 2017- Suzhou Tongji Fintech Research Institute. All Rights Reserved.
46 | Licensed under the Apache License, Version 2.0 (the "License");
47 |
48 | you may not use this file except in compliance with the License.
49 | You may obtain a copy of the License at
50 | http://www.apache.org/licenses/LICENSE-2.0
51 | Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
52 |
53 | See the License for the specific language governing permissions and limitations under the License.
54 | =======
55 |
56 |
57 |
58 |
59 |
--------------------------------------------------------------------------------
/sm4/sm4_gcm_test.go:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright Hyperledger-TWGC All Rights Reserved.
3 | Licensed under the Apache License, Version 2.0 (the "License");
4 | you may not use this file except in compliance with the License.
5 | You may obtain a copy of the License at
6 |
7 | http://www.apache.org/licenses/LICENSE-2.0
8 |
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
14 |
15 | writed by Zhiwei Yan, 2020 Oct
16 | */
17 |
18 | package sm4
19 |
20 | import (
21 | "bytes"
22 | "fmt"
23 | "testing"
24 | )
25 |
26 |
27 | func TestSM4GCM(t *testing.T){
28 | key := []byte("1234567890abcdef")
29 | data := []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10}
30 | IV :=make([]byte,BlockSize)
31 | testA:=[][]byte{ // the length of the A can be random
32 | []byte{},
33 | []byte{0x01, 0x23, 0x45, 0x67, 0x89},
34 | []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10},
35 | }
36 | for _,A:=range testA{
37 | gcmMsg,T,err:=Sm4GCM(key,IV,data,A,true)
38 | if err !=nil{
39 | t.Errorf("sm4 enc error:%s", err)
40 | }
41 | fmt.Printf("gcmMsg = %x\n", gcmMsg)
42 | gcmDec,T_,err:=Sm4GCM(key,IV,gcmMsg,A,false)
43 | if err != nil{
44 | t.Errorf("sm4 dec error:%s", err)
45 | }
46 | fmt.Printf("gcmDec = %x\n", gcmDec)
47 | if bytes.Compare(T,T_)==0{
48 | fmt.Println("authentication successed")
49 | }
50 | //Failed Test : if we input the different A , that will be a falied result.
51 | A= []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd}
52 | gcmDec,T_,err=Sm4GCM(key,IV,gcmMsg,A ,false)
53 | if err != nil{
54 | t.Errorf("sm4 dec error:%s", err)
55 | }
56 | if bytes.Compare(T,T_)!=0{
57 | fmt.Println("authentication failed")
58 | }
59 | }
60 |
61 | }
--------------------------------------------------------------------------------
/sm4/padding/README.md:
--------------------------------------------------------------------------------
1 | # PCSK#7 填充读写流
2 |
3 | 直接使用分块加密,往往需要手动完成填充和去填充的过程。流程较为固定,但是比较繁琐,对于文件和流的处理,不是很友好。
4 |
5 | PKCS#7填充和去除填充:
6 |
7 | - `padding.PKCS7PaddingReader` 写入结束是添加填充
8 | - `padding.PKCS7PaddingWriter` 读取时去除填充
9 |
10 | 封装的填充模式加密:
11 |
12 | - `padding.P7BlockEnc`
13 | - `padding.P7BlockDecrypt`
14 |
15 | 以上方法简化了,对文件和流类型的加密解密过程。
16 |
17 | ## 带填充的模式加密和解密
18 |
19 | > 流:实现了 `io.Writer`、`io.Reader`接口的类型。
20 |
21 | 流的SM4分块CBC模式加密:
22 |
23 | ```go
24 | func main() {
25 | src := bytes.Repeat([]byte{7}, 16)
26 | srcIn := bytes.NewBuffer(src)
27 | encOut := bytes.NewBuffer(make([]byte, 0, 1024))
28 |
29 | key := make([]byte, 16)
30 | iv := make([]byte, 16)
31 | _, _ = rand.Read(key)
32 | _, _ = rand.Read(iv)
33 | fmt.Printf("key: %02X\n", key)
34 | fmt.Printf("iv : %02X\n", iv)
35 | block, err := sm4.NewCipher(key)
36 | if err != nil {
37 | panic(err)
38 | }
39 | encrypter := cipher.NewCBCEncrypter(block, iv)
40 | // P7填充的CBC加密
41 | err = padding.P7BlockEnc(encrypter, srcIn, encOut)
42 | if err != nil {
43 | panic(err)
44 | }
45 | fmt.Printf("原文: %02X\n", src)
46 | fmt.Printf("加密: %02X\n", encOut.Bytes())
47 | }
48 | ```
49 |
50 | 流的SM4分块CBC模式解密:
51 |
52 | ```go
53 | func main() {
54 | /**
55 | key: 4C9CA3D17263F6F558D65ADB561465BD
56 | iv : 221908D1C4BD730BEB011319D1368E49
57 | 原文: 07070707070707070707070707070707
58 | 加密: 310CA2472DCE15CCC58E1BE69B876002F443556CCFB86B1BA0341B6BFBED4C1A
59 | */
60 | encOut := bytes.NewBuffer(make([]byte, 0, 1024))
61 | key,_ := hex.DecodeString("4C9CA3D17263F6F558D65ADB561465BD")
62 | iv,_ := hex.DecodeString("221908D1C4BD730BEB011319D1368E49")
63 | block, err := sm4.NewCipher(key)
64 | if err != nil {
65 | panic(err)
66 | }
67 | ciphertext, _ := hex.DecodeString("310CA2472DCE15CCC58E1BE69B876002F443556CCFB86B1BA0341B6BFBED4C1A")
68 | cipherReader := bytes.NewReader(ciphertext)
69 | decrypter := cipher.NewCBCDecrypter(block, iv)
70 | decOut := bytes.NewBuffer(make([]byte, 0, 1024))
71 | err = padding.P7BlockDecrypt(decrypter, ciphertext, decOut)
72 | if err != nil {
73 | panic(err)
74 | }
75 |
76 | fmt.Printf("解密: %02X\n", decOut.Bytes())
77 | }
78 | ```
79 |
80 | ## PKCS#7填充
81 |
82 | 见测试用例: [pkcs7_padding_io_test.go](./pkcs7_padding_io_test.go)
83 |
--------------------------------------------------------------------------------
/gmtls/simple_round_trip.go:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright Suzhou Tongji Fintech Research Institute 2017 All Rights Reserved.
3 | Licensed under the Apache License, Version 2.0 (the "License");
4 | you may not use this file except in compliance with the License.
5 | You may obtain a copy of the License at
6 |
7 | http://www.apache.org/licenses/LICENSE-2.0
8 |
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
14 | */
15 |
16 | package gmtls
17 |
18 | import (
19 | "bufio"
20 | "fmt"
21 | "io"
22 | "net"
23 | "net/http"
24 | "sync"
25 | )
26 |
27 | // SimpleRoundTripper 简单的单次HTTP/HTTPS(国密) 连接往返器
28 | // 每次建立新的连接
29 | type SimpleRoundTripper struct {
30 | lock sync.Mutex
31 | tlsConfig *Config
32 | }
33 |
34 | func NewSimpleRoundTripper(cfg *Config) *SimpleRoundTripper {
35 | return &SimpleRoundTripper{tlsConfig: cfg}
36 | }
37 |
38 | func (s *SimpleRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
39 | // 加锁保证线程安全
40 | s.lock.Lock()
41 | defer s.lock.Unlock()
42 |
43 | scheme := req.URL.Scheme
44 | isHTTP := scheme == "http" || scheme == "https"
45 | if !isHTTP {
46 | return nil, fmt.Errorf("仅支持http/https协议")
47 | }
48 |
49 | // 获取主机名 和 端口
50 | hostname := req.URL.Hostname()
51 | port := req.URL.Port()
52 | address := net.JoinHostPort(hostname, port)
53 |
54 | var conn io.ReadWriteCloser
55 | var err error
56 | // 根据协议建立连接
57 | if scheme == "http" {
58 | // HTTP 协议建立TCP连接
59 | conn, err = net.Dial("tcp", address)
60 | if err != nil {
61 | return nil, err
62 | }
63 | } else {
64 | // HTTPS 协议建立TLS连接
65 | conn, err = Dial("tcp", address, s.tlsConfig)
66 | if err != nil {
67 | return nil, err
68 | }
69 | }
70 | defer conn.Close()
71 |
72 | // 把请求写入连接中,发起请求
73 | err = req.Write(conn)
74 | if err != nil {
75 | return nil, err
76 | }
77 | // 从连接中读取
78 | response, err := http.ReadResponse(bufio.NewReader(conn), req)
79 | if err != nil {
80 | return nil, err
81 | }
82 | // 协议升级时,替换Body实现
83 | if response.StatusCode == http.StatusSwitchingProtocols {
84 | response.Body = conn
85 | }
86 | return response, nil
87 | }
88 |
--------------------------------------------------------------------------------
/pkcs12/pkcs12_test.go:
--------------------------------------------------------------------------------
1 | // Copyright 2015 The Go Authors. All rights reserved.
2 | // Use of this source code is governed by a BSD-style
3 | // license that can be found in the LICENSE file.
4 |
5 | package pkcs12
6 |
7 | import (
8 | "encoding/base64"
9 | "fmt"
10 | "io/ioutil"
11 | "os"
12 | "testing"
13 |
14 | "github.com/tjfoc/gmsm/sm2"
15 | "github.com/tjfoc/gmsm/x509"
16 | )
17 |
18 | func Test_P12Encrypt(t *testing.T) {
19 | str := "MIICiTCCAi6gAwIBAgIIICAEFwACVjAwCgYIKoEcz1UBg3UwdjEcMBoGA1UEAwwTU21hcnRDQV9UZXN0X1NNMl9DQTEVMBMGA1UECwwMU21hcnRDQV9UZXN0MRAwDgYDVQQKDAdTbWFydENBMQ8wDQYDVQQHDAbljZfkuqwxDzANBgNVBAgMBuaxn+iLjzELMAkGA1UEBhMCQ04wHhcNMjAwNDE3MDYwNjA4WhcNMTkwOTAzMDE1MzE5WjCBrjFGMEQGA1UELQw9YXBpX2NhX1RFU1RfVE9fUEhfUkFfVE9OR0pJX2FlNTA3MGNiY2E4NTQyYzliYmJmOTRmZjcwNThkNmEzMTELMAkGA1UEBhMCQ04xDTALBgNVBAgMBG51bGwxDTALBgNVBAcMBG51bGwxFTATBgNVBAoMDENGQ0FTTTJBR0VOVDENMAsGA1UECwwEbnVsbDETMBEGA1UEAwwKY2hlbnh1QDEwNDBZMBMGByqGSM49AgEGCCqBHM9VAYItA0IABAWeikXULbz1RqgmVzJWtSDMa3f9wirzwnceb1WIWxTqJaY+3xNlsM63oaIKJCD6pZu14EDkLS0FTP1uX3EySOajbTBrMAsGA1UdDwQEAwIGwDAdBgNVHQ4EFgQUbMrrNQDS1B1yjyrkgq2FWGi5zRcwHwYDVR0jBBgwFoAUXPO6JYzCZQzsZ+++3Y1rp16v46wwDAYDVR0TBAUwAwEB/zAOBggqgRzQFAQBAQQCBQAwCgYIKoEcz1UBg3UDSQAwRgIhAMcbwSDvL78qDSoqQh/019EEk4UNHP7zko0t1GueffTnAiEAupHr3k4vWSWV1SEqds+q8u4CbRuuRDvBOQ6od8vGzjM="
20 | decodeBytes, err := base64.StdEncoding.DecodeString(str)
21 | x, err := x509.ParseCertificate(decodeBytes)
22 | priv, err := sm2.GenerateKey(nil) // 生成密钥对
23 | if err != nil {
24 | fmt.Print(err)
25 | return
26 | }
27 | privPem, err := x509.WritePrivateKeyToPem(priv, nil) // 生成密钥文件
28 | if err != nil {
29 | t.Fatal(err)
30 | }
31 | err = ioutil.WriteFile("priv.pem", privPem, os.FileMode(0644))
32 | if err != nil {
33 | t.Fatal(err)
34 | }
35 | privKey, err := x509.ReadPrivateKeyFromPem(privPem, nil) // 读取密钥
36 | if err != nil {
37 | t.Fatal(err)
38 | }
39 | SM2P12Encrypt(x, "123", privKey, "test.p12") //根据证书与私钥生成带密码的p12证书
40 |
41 | }
42 | func Test_P12Dncrypt(t *testing.T) {
43 | certificate, priv, err := SM2P12Decrypt("test.p12", "123") //根据密码读取P12证书
44 | if err != nil {
45 | t.Fatal(err)
46 | }
47 | privPem, _ := ioutil.ReadFile("priv.pem")
48 | privatekey, err := x509.ReadPrivateKeyFromPem(privPem, nil)
49 | if err != nil {
50 | t.Fatal(err)
51 | }
52 | fmt.Println(certificate.Issuer)
53 | fmt.Println(privatekey.D.Cmp(priv.D) == 0)
54 | fmt.Println(priv.IsOnCurve(priv.X, priv.Y))
55 | }
56 |
--------------------------------------------------------------------------------
/sm4/utils.go:
--------------------------------------------------------------------------------
1 | package sm4
2 |
3 | import (
4 | "crypto/rand"
5 | "crypto/x509"
6 | "encoding/pem"
7 | "errors"
8 | "io/ioutil"
9 | )
10 |
11 | // ReadKeyFromPem will return SM4Key from PEM format data.
12 | func ReadKeyFromPem(data []byte, pwd []byte) (SM4Key, error) {
13 | block, _ := pem.Decode(data)
14 | if block == nil {
15 | return nil, errors.New("SM4: pem decode failed")
16 | }
17 | if x509.IsEncryptedPEMBlock(block) {
18 | if block.Type != "SM4 ENCRYPTED KEY" {
19 | return nil, errors.New("SM4: unknown type")
20 | }
21 | if pwd == nil {
22 | return nil, errors.New("SM4: need passwd")
23 | }
24 | data, err := x509.DecryptPEMBlock(block, pwd)
25 | if err != nil {
26 | return nil, err
27 | }
28 | return data, nil
29 | }
30 | if block.Type != "SM4 KEY" {
31 | return nil, errors.New("SM4: unknown type")
32 | }
33 | return block.Bytes, nil
34 | }
35 |
36 | // ReadKeyFromPemFile will return SM4Key from filename that saved PEM format data.
37 | func ReadKeyFromPemFile(FileName string, pwd []byte) (SM4Key, error) {
38 | data, err := ioutil.ReadFile(FileName)
39 | if err != nil {
40 | return nil, err
41 | }
42 | return ReadKeyFromPem(data, pwd)
43 | }
44 |
45 | // WriteKeyToPem will convert SM4Key to PEM format data and return it.
46 | func WriteKeyToPem(key SM4Key, pwd []byte) ([]byte, error) {
47 | if pwd != nil {
48 | block, err := x509.EncryptPEMBlock(rand.Reader,
49 | "SM4 ENCRYPTED KEY", key, pwd, x509.PEMCipherAES256) //Use AES256 algorithms to encrypt SM4KEY
50 | if err != nil {
51 | return nil, err
52 | }
53 | return pem.EncodeToMemory(block), nil
54 | } else {
55 | block := &pem.Block{
56 | Type: "SM4 KEY",
57 | Bytes: key,
58 | }
59 | return pem.EncodeToMemory(block), nil
60 | }
61 | }
62 |
63 | // WriteKeyToPemFile will convert SM4Key to PEM format data, then write it
64 | // into the input filename.
65 | func WriteKeyToPemFile(FileName string, key SM4Key, pwd []byte) error {
66 | var block *pem.Block
67 | var err error
68 | if pwd != nil {
69 | block, err = x509.EncryptPEMBlock(rand.Reader,
70 | "SM4 ENCRYPTED KEY", key, pwd, x509.PEMCipherAES256)
71 | if err != nil {
72 | return err
73 | }
74 | } else {
75 | block = &pem.Block{
76 | Type: "SM4 KEY",
77 | Bytes: key,
78 | }
79 | }
80 | pemBytes := pem.EncodeToMemory(block)
81 | err = ioutil.WriteFile(FileName, pemBytes, 0666)
82 | if err != nil {
83 | return err
84 | }
85 | return nil
86 | }
87 |
--------------------------------------------------------------------------------
/gmtls/http_client.go:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright Suzhou Tongji Fintech Research Institute 2017 All Rights Reserved.
3 | Licensed under the Apache License, Version 2.0 (the "License");
4 | you may not use this file except in compliance with the License.
5 | You may obtain a copy of the License at
6 |
7 | http://www.apache.org/licenses/LICENSE-2.0
8 |
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
14 | */
15 |
16 | package gmtls
17 |
18 | import (
19 | "context"
20 | "net"
21 | "net/http"
22 | "time"
23 |
24 | "github.com/tjfoc/gmsm/x509"
25 | )
26 |
27 | // NewHTTPSClient 创建国密HTTPS客户端,只对服务端进行身份认证(验证服务端证书)。
28 | // pool: 根证书链
29 | func NewHTTPSClient(pool *x509.CertPool) *http.Client {
30 | return &http.Client{
31 | Transport: NewSimpleRoundTripper(&Config{
32 | GMSupport: &GMSupport{},
33 | RootCAs: pool,
34 | }),
35 | }
36 | }
37 |
38 | // NewAuthHTTPSClient 创建双向身份认证国密HTTPS客户端
39 | //
40 | // pool: 根证书链
41 | // clientAuthCert: 客户端认证密钥对和证书
42 | func NewAuthHTTPSClient(pool *x509.CertPool, clientAuthCert *Certificate) *http.Client {
43 | return &http.Client{
44 | Transport: NewSimpleRoundTripper(&Config{
45 | GMSupport: &GMSupport{},
46 | RootCAs: pool,
47 | Certificates: []Certificate{*clientAuthCert},
48 | }),
49 | }
50 | }
51 |
52 | // NewCustomHTTPSClient 创建自定义国密HTTPS客户端
53 | // 通过自定义TLS参数定制TLS实现细节,如进行双向身份认证等。
54 | func NewCustomHTTPSClient(config *Config) *http.Client {
55 | if config == nil {
56 | return &http.Client{}
57 | }
58 |
59 | return &http.Client{
60 | Transport: newDefaultGMHttpClientTransport(config),
61 | }
62 | }
63 |
64 | func newDefaultGMHttpClientTransport(tlsConfig *Config) http.RoundTripper {
65 | return &http.Transport{
66 | DialTLSContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
67 |
68 | dialer := &net.Dialer{}
69 |
70 | conn, err := DialWithDialer(dialer, network, addr, tlsConfig)
71 | if err != nil {
72 | return nil, err
73 | }
74 |
75 | return conn, nil
76 | },
77 | Dial: (&net.Dialer{
78 | Timeout: 10 * time.Second,
79 | KeepAlive: 60 * time.Second,
80 | }).Dial,
81 | TLSHandshakeTimeout: 10 * time.Second,
82 | IdleConnTimeout: 30 * time.Second,
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | ## 更新日志
2 | ### 2.0 更新(June 9,2021)
3 | - [FIX] SM2公钥压缩格式前缀修改
4 | - [FIX]]国密tls部分bug修改
5 | - [FIX]]SM4_gcm模式bug修改
6 | - [New] 公私钥16进制格式导入导出
7 | - [New] SM4加密可设置IV值
8 | - [New] 国密tls与非国密自适应实现
9 |
10 |
11 | ### 1.4 更新(Sep 15,2020)
12 | **破坏性更新**
13 | - [FIX] SM2 生成私钥、签名及加密方法加入随机数,可使用外部随机数。
14 | - [FIX] 公私钥及证书从pem格式[]byte数据中导入导出,不再从pem格式File文件导入导出。
15 | - [FIX] SM2证书相关实现代码单独移至X509包中。
16 | - [FIX] 代码优化,删除无用方法
17 | - [New] SM4加密ecb、cbc模式实现
18 | - [New] 国密tls实现移至该库gmtls包中
19 | - [New] 国密tls实现使用双证书
20 |
21 | ### 1.2 更新(Feb 20, 2019)
22 |
23 | - [NEW] 实现PKCS#7签名及验签
24 | - [FIX] SM2 签名及验签方法完全遵循标准GM/T 0003系列,兼容CFCA Java-SDK
25 |
26 | **破坏性更新,证书与之前版本不兼容**
27 |
28 | ### 1.1.1更新
29 | - 新增以下函数支持用户其他信息
30 | SignDigitToSignData 将签名所得的大数r和s转换为签名的格式
31 | Sm2Sign 支持用户信息的签名
32 | Sm2Verify 支持用户信息的验签
33 |
34 |
35 | ### 1.1.0更新:
36 | - 改进新能,具体提升如下
37 | 注:本次优化并不彻底,只是第一次尝试优化,后续有时间还会继续优化
38 | ```
39 | old:
40 | generate key:
41 | BenchmarkSM2-4 1000 2517147 ns/op 1156476 B/op 11273 allocs/op
42 | sign:
43 | BenchmarkSM2-4 300 6297498 ns/op 2321890 B/op 22653 allocs/op
44 | verify:
45 | BenchmarkSM2-4 2000 8557215 ns/op 3550626 B/op 34627 allocs/op
46 | encrypt:
47 | BenchmarkSM2-4 2000 8304840 ns/op 3483113 B/op 33967 allocs/op
48 | decrypt:
49 | BenchmarkSM2-4 2000 5726181 ns/op 2321728 B/op 22644 allocs/op
50 | new:
51 | generate key:
52 | BenchmarkSM2-4 5000 303656 ns/op 2791 B/op 41 allocs/op
53 | sign:
54 | BenchmarkSM2-4 2000 652465 ns/op 8828 B/op 133 allocs/op
55 | verify:
56 | BenchmarkSM2-4 1000 2004511 ns/op 122709 B/op 1738 allocs/op
57 | encrpyt:
58 | BenchmarkSM2-4 1000 1984419 ns/op 118560 B/op 1687 allocs/op
59 | decrypt:
60 | BenchmarkSM2-4 1000 1725001 ns/op 118331 B/op 1679 allocs/op
61 | ```
62 |
63 | ### 1.0.1 更新:
64 | - 添加全局的sbox改进sm4效率(by https://github.com/QwertyJack)
65 |
66 |
67 | ### 1.0 更新:
68 | - 添加以下oid
69 | SM3WithSM2 1.2.156.10197.1.501
70 | SHA1WithSM2 1.2.156.10197.1.502
71 | SHA256WithSM2 1.2.156.10197.1.503
72 |
73 | - x509生成的证书如今可以使用SM3作为hash算法
74 |
75 | - 引入了以下hash算法
76 | RIPEMD160
77 | SHA3_256
78 | SHA3_384
79 | SHA3_512
80 | SHA3_SM3
81 | 用户需要自己安装golang.org/x/crypto
82 |
83 |
84 |
85 |
86 |
--------------------------------------------------------------------------------
/gmtls/gm_handshake_messages.go:
--------------------------------------------------------------------------------
1 | // Copyright 2009 The Go Authors. All rights reserved.
2 | // Copyright 2009 The Go Authors. All rights reserved.
3 | // Use of this source code is governed by a BSD-style
4 | // license that can be found in the LICENSE file.
5 |
6 | package gmtls
7 |
8 | import "bytes"
9 |
10 | type certificateRequestMsgGM struct {
11 | raw []byte
12 |
13 | certificateTypes []byte
14 | certificateAuthorities [][]byte
15 | }
16 |
17 | func (m *certificateRequestMsgGM) equal(i interface{}) bool {
18 | m1, ok := i.(*certificateRequestMsgGM)
19 | if !ok {
20 | return false
21 | }
22 |
23 | return bytes.Equal(m.raw, m1.raw) &&
24 | bytes.Equal(m.certificateTypes, m1.certificateTypes) &&
25 | eqByteSlices(m.certificateAuthorities, m1.certificateAuthorities)
26 | }
27 |
28 | func (m *certificateRequestMsgGM) marshal() (x []byte) {
29 | if m.raw != nil {
30 | return m.raw
31 | }
32 |
33 | // See https://tools.ietf.org/html/rfc4346#section-7.4.4
34 | length := 1 + len(m.certificateTypes) + 2
35 | casLength := 0
36 | for _, ca := range m.certificateAuthorities {
37 | casLength += 2 + len(ca)
38 | }
39 | length += casLength
40 |
41 | x = make([]byte, 4+length)
42 | x[0] = typeCertificateRequest
43 | x[1] = uint8(length >> 16)
44 | x[2] = uint8(length >> 8)
45 | x[3] = uint8(length)
46 |
47 | x[4] = uint8(len(m.certificateTypes))
48 |
49 | copy(x[5:], m.certificateTypes)
50 | y := x[5+len(m.certificateTypes):]
51 |
52 | y[0] = uint8(casLength >> 8)
53 | y[1] = uint8(casLength)
54 | y = y[2:]
55 | for _, ca := range m.certificateAuthorities {
56 | y[0] = uint8(len(ca) >> 8)
57 | y[1] = uint8(len(ca))
58 | y = y[2:]
59 | copy(y, ca)
60 | y = y[len(ca):]
61 | }
62 |
63 | m.raw = x
64 | return
65 | }
66 |
67 | func (m *certificateRequestMsgGM) unmarshal(data []byte) bool {
68 | m.raw = data
69 |
70 | if len(data) < 5 {
71 | return false
72 | }
73 |
74 | length := uint32(data[1])<<16 | uint32(data[2])<<8 | uint32(data[3])
75 | if uint32(len(data))-4 != length {
76 | return false
77 | }
78 |
79 | numCertTypes := int(data[4])
80 | data = data[5:]
81 | if numCertTypes == 0 || len(data) <= numCertTypes {
82 | return false
83 | }
84 |
85 | m.certificateTypes = make([]byte, numCertTypes)
86 | if copy(m.certificateTypes, data) != numCertTypes {
87 | return false
88 | }
89 |
90 | data = data[numCertTypes:]
91 |
92 | if len(data) < 2 {
93 | return false
94 | }
95 | casLength := uint16(data[0])<<8 | uint16(data[1])
96 | data = data[2:]
97 | if len(data) < int(casLength) {
98 | return false
99 | }
100 | cas := make([]byte, casLength)
101 | copy(cas, data)
102 | data = data[casLength:]
103 |
104 | m.certificateAuthorities = nil
105 | for len(cas) > 0 {
106 | if len(cas) < 2 {
107 | return false
108 | }
109 | caLen := uint16(cas[0])<<8 | uint16(cas[1])
110 | cas = cas[2:]
111 |
112 | if len(cas) < int(caLen) {
113 | return false
114 | }
115 |
116 | m.certificateAuthorities = append(m.certificateAuthorities, cas[:caLen])
117 | cas = cas[caLen:]
118 | }
119 |
120 | return len(data) == 0
121 | }
122 |
123 |
--------------------------------------------------------------------------------
/gmtls/gmcredentials/credentials_test.go:
--------------------------------------------------------------------------------
1 | package gmcredentials
2 |
3 | import (
4 | "fmt"
5 | "io/ioutil"
6 | "log"
7 | "net"
8 | "testing"
9 | "time"
10 |
11 | "github.com/tjfoc/gmsm/gmtls"
12 | "github.com/tjfoc/gmsm/gmtls/gmcredentials/echo"
13 | "github.com/tjfoc/gmsm/x509"
14 | "golang.org/x/net/context"
15 | "google.golang.org/grpc"
16 | )
17 |
18 | const (
19 | port = ":50051"
20 | address = "localhost:50051"
21 | )
22 |
23 | var end chan bool
24 |
25 | type server struct{}
26 |
27 | func (s *server) Echo(ctx context.Context, req *echo.EchoRequest) (*echo.EchoResponse, error) {
28 | return &echo.EchoResponse{Result: req.Req}, nil
29 | }
30 |
31 | const ca = "testdata/ca.cert"
32 | const signCert = "testdata/sign.cert"
33 | const signKey = "testdata/sign.key"
34 | const encryptCert = "testdata/encrypt.cert"
35 | const encryptKey = "testdata/encrypt.key"
36 |
37 | const userCert = "testdata/user.cert"
38 | const userKey = "testdata/user.key"
39 |
40 | func serverRun() {
41 | signCert, err := gmtls.LoadX509KeyPair(signCert, signKey)
42 | if err != nil {
43 | log.Fatal(err)
44 | }
45 |
46 | encryptCert, err := gmtls.LoadX509KeyPair(encryptCert, encryptKey)
47 | if err != nil {
48 | log.Fatal(err)
49 | }
50 | certPool := x509.NewCertPool()
51 | cacert, err := ioutil.ReadFile(ca)
52 | if err != nil {
53 | log.Fatal(err)
54 | }
55 | certPool.AppendCertsFromPEM(cacert)
56 | lis, err := net.Listen("tcp", port)
57 | if err != nil {
58 | log.Fatalf("fail to listen: %v", err)
59 | }
60 | creds := NewTLS(&gmtls.Config{
61 | GMSupport: &gmtls.GMSupport{},
62 | ClientAuth: gmtls.RequireAndVerifyClientCert,
63 | Certificates: []gmtls.Certificate{signCert, encryptCert},
64 | ClientCAs: certPool,
65 | })
66 | s := grpc.NewServer(grpc.Creds(creds))
67 | echo.RegisterEchoServer(s, &server{})
68 | err = s.Serve(lis)
69 | if err != nil {
70 | log.Fatalf("Serve: %v", err)
71 | }
72 | }
73 |
74 | func clientRun() {
75 | cert, err := gmtls.LoadX509KeyPair(userCert, userKey)
76 | if err != nil {
77 | log.Fatal(err)
78 | }
79 | certPool := x509.NewCertPool()
80 | cacert, err := ioutil.ReadFile(ca)
81 | if err != nil {
82 | log.Fatal(err)
83 | }
84 | certPool.AppendCertsFromPEM(cacert)
85 | creds := NewTLS(&gmtls.Config{
86 | GMSupport: &gmtls.GMSupport{},
87 | ServerName: "test.example.com",
88 | Certificates: []gmtls.Certificate{cert},
89 | RootCAs: certPool,
90 | ClientAuth: gmtls.RequireAndVerifyClientCert,
91 | })
92 | conn, err := grpc.Dial(address, grpc.WithTransportCredentials(creds))
93 | if err != nil {
94 | log.Fatalf("cannot to connect: %v", err)
95 | }
96 | defer conn.Close()
97 | c := echo.NewEchoClient(conn)
98 | echoTest(c)
99 | end <- true
100 | }
101 |
102 | func echoTest(c echo.EchoClient) {
103 | r, err := c.Echo(context.Background(), &echo.EchoRequest{Req: "hello"})
104 | if err != nil {
105 | log.Fatalf("failed to echo: %v", err)
106 | }
107 | fmt.Printf("%s\n", r.Result)
108 | }
109 |
110 | func Test(t *testing.T) {
111 | end = make(chan bool, 64)
112 | go serverRun()
113 | time.Sleep(1000000)
114 | go clientRun()
115 | <-end
116 | }
117 |
--------------------------------------------------------------------------------
/sm4/padding/pkcs7_padding_io.go:
--------------------------------------------------------------------------------
1 | package padding
2 |
3 | import (
4 | "bytes"
5 | "errors"
6 | "io"
7 | )
8 |
9 | // PKCS7PaddingReader 符合PKCS#7填充的输入流
10 | type PKCS7PaddingReader struct {
11 | fIn io.Reader
12 | padding io.Reader
13 | blockSize int
14 | readed int64
15 | eof bool
16 | eop bool
17 | }
18 |
19 | // NewPKCS7PaddingReader 创建PKCS7填充Reader
20 | // in: 输入流
21 | // blockSize: 分块大小
22 | func NewPKCS7PaddingReader(in io.Reader, blockSize int) *PKCS7PaddingReader {
23 | return &PKCS7PaddingReader{
24 | fIn: in,
25 | padding: nil,
26 | eof: false,
27 | eop: false,
28 | blockSize: blockSize,
29 | }
30 | }
31 |
32 | func (p *PKCS7PaddingReader) Read(buf []byte) (int, error) {
33 | /*
34 | - 读取文件
35 | - 文件长度充足, 直接返还
36 | - 不充足
37 | - 读取到 n 字节, 剩余需要 m 字节
38 | - 从 padding 中读取然后追加到 buff
39 | - EOF 直接返回, 整个Reader end
40 | */
41 | // 都读取完了
42 | if p.eof && p.eop {
43 | return 0, io.EOF
44 | }
45 |
46 | var n, off = 0, 0
47 | var err error
48 | if !p.eof {
49 | // 读取文件
50 | n, err = p.fIn.Read(buf)
51 | if err != nil && !errors.Is(err, io.EOF) {
52 | // 错误返回
53 | return 0, err
54 | }
55 | p.readed += int64(n)
56 | if errors.Is(err, io.EOF) {
57 | // 标志文件结束
58 | p.eof = true
59 | }
60 | if n == len(buf) {
61 | // 长度足够直接返回
62 | return n, nil
63 | }
64 | // 文件长度已经不足,根据已经已经读取的长度创建Padding
65 | p.newPadding()
66 | // 长度不足向Padding中索要
67 | off = n
68 | }
69 |
70 | if !p.eop {
71 | // 读取流
72 | var n2 = 0
73 | n2, err = p.padding.Read(buf[off:])
74 | n += n2
75 | if errors.Is(err, io.EOF) {
76 | p.eop = true
77 | }
78 | }
79 | return n, err
80 | }
81 |
82 | // 新建Padding
83 | func (p *PKCS7PaddingReader) newPadding() {
84 | if p.padding != nil {
85 | return
86 | }
87 | size := p.blockSize - int(p.readed%int64(p.blockSize))
88 | padding := bytes.Repeat([]byte{byte(size)}, size)
89 | p.padding = bytes.NewReader(padding)
90 | }
91 |
92 | // PKCS7PaddingWriter 符合PKCS#7去除的输入流,最后一个 分组根据会根据填充情况去除填充。
93 | type PKCS7PaddingWriter struct {
94 | cache *bytes.Buffer // 缓存区
95 | swap []byte // 临时交换区
96 | out io.Writer // 输出位置
97 | blockSize int // 分块大小
98 | }
99 |
100 | // NewPKCS7PaddingWriter PKCS#7 填充Writer 可以去除填充
101 | func NewPKCS7PaddingWriter(out io.Writer, blockSize int) *PKCS7PaddingWriter {
102 | cache := bytes.NewBuffer(make([]byte, 0, 1024))
103 | swap := make([]byte, 1024)
104 | return &PKCS7PaddingWriter{out: out, blockSize: blockSize, cache: cache, swap: swap}
105 | }
106 |
107 | // Write 保留一个填充大小的数据,其余全部写入输出中
108 | func (p *PKCS7PaddingWriter) Write(buff []byte) (n int, err error) {
109 | // 写入缓存
110 | n, err = p.cache.Write(buff)
111 | if err != nil {
112 | return 0, err
113 | }
114 | if p.cache.Len() > p.blockSize {
115 | // 把超过一个分组长度的部分读取出来,写入到实际的out中
116 | size := p.cache.Len() - p.blockSize
117 | _, _ = p.cache.Read(p.swap[:size])
118 | _, err = p.out.Write(p.swap[:size])
119 | if err != nil {
120 | return 0, err
121 | }
122 | }
123 | return n, err
124 |
125 | }
126 |
127 | // Final 去除填充写入最后一个分块
128 | func (p *PKCS7PaddingWriter) Final() error {
129 | // 在Write 之后 cache 只会保留一个Block长度数据
130 | b := p.cache.Bytes()
131 | length := len(b)
132 | if length != p.blockSize {
133 | return errors.New("非法的PKCS7填充")
134 | }
135 | if length == 0 {
136 | return nil
137 | }
138 | unpadding := int(b[length-1])
139 | if unpadding > p.blockSize || unpadding == 0 {
140 | return errors.New("非法的PKCS7填充")
141 | }
142 | _, err := p.out.Write(b[:(length - unpadding)])
143 | return err
144 | }
145 |
--------------------------------------------------------------------------------
/pkcs12/safebags.go:
--------------------------------------------------------------------------------
1 | // Copyright 2015 The Go Authors. All rights reserved.
2 | // Use of this source code is governed by a BSD-style
3 | // license that can be found in the LICENSE file.
4 |
5 | package pkcs12
6 |
7 | import (
8 | "crypto/rand"
9 | "encoding/asn1"
10 | "errors"
11 | )
12 |
13 | var (
14 | // see https://tools.ietf.org/html/rfc7292#appendix-D
15 | oidCertTypeX509Certificate = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 9, 22, 1})
16 | oidPKCS8ShroundedKeyBag = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 12, 10, 1, 2})
17 | oidCertBag = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 12, 10, 1, 3})
18 | )
19 |
20 | type certBag struct {
21 | Id asn1.ObjectIdentifier
22 | Data []byte `asn1:"tag:0,explicit"`
23 | }
24 |
25 | func decodePkcs8ShroudedKeyBag(asn1Data, password []byte) (privateKey interface{}, err error) {
26 | pkinfo := new(encryptedPrivateKeyInfo)
27 | if err = unmarshal(asn1Data, pkinfo); err != nil {
28 | return nil, errors.New("go-pkcs12: error decoding PKCS#8 shrouded key bag: " + err.Error())
29 | }
30 |
31 | pkData, err := pbDecrypt(pkinfo, password)
32 | if err != nil {
33 | return nil, errors.New("go-pkcs12: error decrypting PKCS#8 shrouded key bag: " + err.Error())
34 | }
35 |
36 | ret := new(asn1.RawValue)
37 | if err = unmarshal(pkData, ret); err != nil {
38 | return nil, errors.New("go-pkcs12: error unmarshaling decrypted private key: " + err.Error())
39 | }
40 |
41 | if privateKey, err = ParsePKCS8PrivateKey(pkData); err != nil {
42 | return nil, errors.New("go-pkcs12: error parsing PKCS#8 private key: " + err.Error())
43 | }
44 |
45 | return privateKey, nil
46 | }
47 |
48 | func encodePkcs8ShroudedKeyBag(privateKey interface{}, password []byte) (asn1Data []byte, err error) {
49 | var pkData []byte
50 | if pkData, err = marshalPKCS8PrivateKey(privateKey); err != nil {
51 | return nil, errors.New("go-pkcs12: error encoding PKCS#8 private key: " + err.Error())
52 | }
53 |
54 | randomSalt := make([]byte, 8)
55 | if _, err = rand.Read(randomSalt); err != nil {
56 | return nil, errors.New("go-pkcs12: error reading random salt: " + err.Error())
57 | }
58 | var paramBytes []byte
59 | if paramBytes, err = asn1.Marshal(pbeParams{Salt: randomSalt, Iterations: 2048}); err != nil {
60 | return nil, errors.New("go-pkcs12: error encoding params: " + err.Error())
61 | }
62 |
63 | var pkinfo encryptedPrivateKeyInfo
64 | pkinfo.AlgorithmIdentifier.Algorithm = oidPBEWithSHAAnd3KeyTripleDESCBC
65 | pkinfo.AlgorithmIdentifier.Parameters.FullBytes = paramBytes
66 |
67 | if err = pbEncrypt(&pkinfo, pkData, password); err != nil {
68 | return nil, errors.New("go-pkcs12: error encrypting PKCS#8 shrouded key bag: " + err.Error())
69 | }
70 |
71 | if asn1Data, err = asn1.Marshal(pkinfo); err != nil {
72 | return nil, errors.New("go-pkcs12: error encoding PKCS#8 shrouded key bag: " + err.Error())
73 | }
74 |
75 | return asn1Data, nil
76 | }
77 |
78 | func decodeCertBag(asn1Data []byte) (x509Certificates []byte, err error) {
79 | bag := new(certBag)
80 | if err := unmarshal(asn1Data, bag); err != nil {
81 | return nil, errors.New("go-pkcs12: error decoding cert bag: " + err.Error())
82 | }
83 | if !bag.Id.Equal(oidCertTypeX509Certificate) {
84 | return nil, NotImplementedError("only X509 certificates are supported")
85 | }
86 | return bag.Data, nil
87 | }
88 |
89 | func encodeCertBag(x509Certificates []byte) (asn1Data []byte, err error) {
90 | var bag certBag
91 | bag.Id = oidCertTypeX509Certificate
92 | bag.Data = x509Certificates
93 | if asn1Data, err = asn1.Marshal(bag); err != nil {
94 | return nil, errors.New("go-pkcs12: error encoding cert bag: " + err.Error())
95 | }
96 | return asn1Data, nil
97 | }
98 |
--------------------------------------------------------------------------------
/API使用说明.md:
--------------------------------------------------------------------------------
1 | # 国密GM/T Go API使用说明
2 |
3 |
4 |
5 | - [国密GM/T Go API使用说明](#国密gmt-go-api使用说明)
6 | - [Go包安装](#go包安装)
7 | - [SM2椭圆曲线公钥密码算法](#sm2椭圆曲线公钥密码算法)
8 | - [代码示例](#代码示例)
9 | - [SM3密码杂凑算法](#sm3密码杂凑算法)
10 | - [代码示例](#代码示例-1)
11 | - [SM4分组密码算法](#sm4分组密码算法)
12 | - [代码示例](#代码示例-2)
13 | - [相关代码示例参考](#相关代码示例参考)
14 | - [国密SSL(TLCP)](#国密ssltlcp)
15 |
16 |
17 |
18 | ## Go包安装
19 |
20 | ```bash
21 | go get -u github.com/tjfoc/gmsm
22 | ```
23 | ## SM2椭圆曲线公钥密码算法
24 |
25 | > SM2椭圆曲线公钥密码算法 Public key cryptographic algorithm SM2 based on elliptic curves
26 |
27 | - 遵循的SM2标准号为: GM/T 0003.1-2012、GM/T 0003.2-2012、GM/T 0003.3-2012、GM/T 0003.4-2012、GM/T 0003.5-2012、GM/T 0009-2012、GM/T 0010-2012
28 | - go package: `github.com/tjfoc/gmsm/sm2`
29 |
30 | ### 代码示例
31 |
32 | ```Go
33 | priv, err := sm2.GenerateKey(rand.Reader) // 生成密钥对
34 | if err != nil {
35 | log.Fatal(err)
36 | }
37 | msg := []byte("Tongji Fintech Research Institute")
38 | pub := &priv.PublicKey
39 | ciphertxt, err := pub.EncryptAsn1(msg,rand.Reader) //sm2加密
40 | if err != nil {
41 | log.Fatal(err)
42 | }
43 | fmt.Printf("加密结果:%x\n",ciphertxt)
44 | plaintxt,err := priv.DecryptAsn1(ciphertxt) //sm2解密
45 | if err != nil {
46 | log.Fatal(err)
47 | }
48 | if !bytes.Equal(msg,plaintxt){
49 | log.Fatal("原文不匹配")
50 | }
51 |
52 | sign,err := priv.Sign(rand.Reader, msg, nil) //sm2签名
53 | if err != nil {
54 | log.Fatal(err)
55 | }
56 | isok := pub.Verify(msg, sign) //sm2验签
57 | fmt.Printf("Verified: %v\n", isok)
58 | ```
59 | ## SM3密码杂凑算法
60 |
61 | > SM3密码杂凑算法 - SM3 cryptographic hash algorithm
62 |
63 | - 遵循的SM3标准号为: GM/T 0004-2012
64 | - g package:`github.com/tjfoc/gmsm/sm3`
65 | - `type SM3 struct` 是原生接口hash.Hash的一个实现
66 |
67 | ### 代码示例
68 |
69 | ```Go
70 | data := "test"
71 | h := sm3.New()
72 | h.Write([]byte(data))
73 | sum := h.Sum(nil)
74 | fmt.Printf("digest value is: %x\n",sum)
75 | ```
76 |
77 | ## SM4分组密码算法
78 |
79 | > SM4分组密码算法 - SM4 block cipher algorithm
80 |
81 | - 遵循的SM4标准号为: GM/T 0002-2012
82 | - go package:`github.com/tjfoc/gmsm/sm4`
83 |
84 | ### 代码示例
85 |
86 | ```Go
87 | import "crypto/cipher"
88 | import "github.com/tjfoc/gmsm/sm4"
89 | import "fmt"
90 |
91 | func main(){
92 | key := []byte("1234567890abcdef")
93 | fmt.Printf("key = %v\n", key)
94 | data := []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10}
95 | fmt.Printf("key = %v\n", key)
96 | fmt.Printf("data = %x\n", data)
97 | iv := []byte("0000000000000000")
98 | err = SetIV(iv)//设置SM4算法实现的IV值,不设置则使用默认值
99 | ecbMsg, err :=sm4.Sm4Ecb(key, data, true) //sm4Ecb模式pksc7填充加密
100 | if err != nil {
101 | t.Errorf("sm4 enc error:%s", err)
102 | return
103 | }
104 | fmt.Printf("ecbMsg = %x\n", ecbMsg)
105 | ecbDec, err := sm4.Sm4Ecb(key, ecbMsg, false) //sm4Ecb模式pksc7填充解密
106 | if err != nil {
107 | t.Errorf("sm4 dec error:%s", err)
108 | return
109 | }
110 | fmt.Printf("ecbDec = %x\n", ecbDec)
111 | }
112 | ```
113 |
114 |
115 | ## 相关代码示例参考
116 |
117 | - [SM2算法 sm2/sm2_test.go](sm2/sm2_test.go)
118 | - [SM3算法 sm3/sm3_test.go](sm3/sm3_test.go)
119 | - [SM4算法 sm4/sm4_test.go](sm4/sm4_test.go)
120 | - [x509国密证书 x509/x509_test.go](x509/x509_test.go)
121 |
122 | ## 国密SSL(TLCP)
123 |
124 | - 国密SSL协议遵循标准:《GM/T 0024-2014 SSL VPN技术规范》
125 | - **国密SSL协议目前升级为TLCP协议,遵循《GBT 38636-2020 信息安全技术 传输层密码协议》**,新增了SM4的GCM加密模式。
126 |
127 | 国密SSL使用详情见文档: [《tjfoc 国密SSL协议快速入门》](gmtls/websvr/README.md)
128 |
129 | 示例入口:
130 |
131 | - [国密HTTPS Web服务器测试用例 gmtls/websvr/websvr.go](gmtls/websvr/websvr.go)
132 | - [国密TLS GRPC测试用例 gmtls/websvr/credentials_test.go](gmtls/gmcredentials/credentials_test.go)
133 |
--------------------------------------------------------------------------------
/x509/pkcs1.go:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright Suzhou Tongji Fintech Research Institute 2017 All Rights Reserved.
3 | Licensed under the Apache License, Version 2.0 (the "License");
4 | you may not use this file except in compliance with the License.
5 | You may obtain a copy of the License at
6 |
7 | http://www.apache.org/licenses/LICENSE-2.0
8 |
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
14 | */
15 |
16 | package x509
17 |
18 | import (
19 | "crypto/rsa"
20 | "encoding/asn1"
21 | "errors"
22 | "math/big"
23 | )
24 |
25 | // pkcs1PrivateKey is a structure which mirrors the PKCS#1 ASN.1 for an RSA private key.
26 | type pkcs1PrivateKey struct {
27 | Version int
28 | N *big.Int
29 | E int
30 | D *big.Int
31 | P *big.Int
32 | Q *big.Int
33 | // We ignore these values, if present, because rsa will calculate them.
34 | Dp *big.Int `asn1:"optional"`
35 | Dq *big.Int `asn1:"optional"`
36 | Qinv *big.Int `asn1:"optional"`
37 |
38 | AdditionalPrimes []pkcs1AdditionalRSAPrime `asn1:"optional,omitempty"`
39 | }
40 |
41 | type pkcs1AdditionalRSAPrime struct {
42 | Prime *big.Int
43 |
44 | // We ignore these values because rsa will calculate them.
45 | Exp *big.Int
46 | Coeff *big.Int
47 | }
48 |
49 | // ParsePKCS1PrivateKey returns an RSA private key from its ASN.1 PKCS#1 DER encoded form.
50 | func ParsePKCS1PrivateKey(der []byte) (*rsa.PrivateKey, error) {
51 | var priv pkcs1PrivateKey
52 | rest, err := asn1.Unmarshal(der, &priv)
53 | if len(rest) > 0 {
54 | return nil, asn1.SyntaxError{Msg: "trailing data"}
55 | }
56 | if err != nil {
57 | return nil, err
58 | }
59 |
60 | if priv.Version > 1 {
61 | return nil, errors.New("x509: unsupported private key version")
62 | }
63 |
64 | if priv.N.Sign() <= 0 || priv.D.Sign() <= 0 || priv.P.Sign() <= 0 || priv.Q.Sign() <= 0 {
65 | return nil, errors.New("x509: private key contains zero or negative value")
66 | }
67 |
68 | key := new(rsa.PrivateKey)
69 | key.PublicKey = rsa.PublicKey{
70 | E: priv.E,
71 | N: priv.N,
72 | }
73 |
74 | key.D = priv.D
75 | key.Primes = make([]*big.Int, 2+len(priv.AdditionalPrimes))
76 | key.Primes[0] = priv.P
77 | key.Primes[1] = priv.Q
78 | for i, a := range priv.AdditionalPrimes {
79 | if a.Prime.Sign() <= 0 {
80 | return nil, errors.New("x509: private key contains zero or negative prime")
81 | }
82 | key.Primes[i+2] = a.Prime
83 | // We ignore the other two values because rsa will calculate
84 | // them as needed.
85 | }
86 |
87 | err = key.Validate()
88 | if err != nil {
89 | return nil, err
90 | }
91 | key.Precompute()
92 |
93 | return key, nil
94 | }
95 |
96 | // MarshalPKCS1PrivateKey converts a private key to ASN.1 DER encoded form.
97 | func MarshalPKCS1PrivateKey(key *rsa.PrivateKey) []byte {
98 | key.Precompute()
99 |
100 | version := 0
101 | if len(key.Primes) > 2 {
102 | version = 1
103 | }
104 |
105 | priv := pkcs1PrivateKey{
106 | Version: version,
107 | N: key.N,
108 | E: key.PublicKey.E,
109 | D: key.D,
110 | P: key.Primes[0],
111 | Q: key.Primes[1],
112 | Dp: key.Precomputed.Dp,
113 | Dq: key.Precomputed.Dq,
114 | Qinv: key.Precomputed.Qinv,
115 | }
116 |
117 | priv.AdditionalPrimes = make([]pkcs1AdditionalRSAPrime, len(key.Precomputed.CRTValues))
118 | for i, values := range key.Precomputed.CRTValues {
119 | priv.AdditionalPrimes[i].Prime = key.Primes[2+i]
120 | priv.AdditionalPrimes[i].Exp = values.Exp
121 | priv.AdditionalPrimes[i].Coeff = values.Coeff
122 | }
123 |
124 | b, _ := asn1.Marshal(priv)
125 | return b
126 | }
127 |
128 | // rsaPublicKey reflects the ASN.1 structure of a PKCS#1 public key.
129 | type rsaPublicKey struct {
130 | N *big.Int
131 | E int
132 | }
133 |
--------------------------------------------------------------------------------
/gmtls/alert.go:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright Suzhou Tongji Fintech Research Institute 2017 All Rights Reserved.
3 | Licensed under the Apache License, Version 2.0 (the "License");
4 | you may not use this file except in compliance with the License.
5 | You may obtain a copy of the License at
6 |
7 | http://www.apache.org/licenses/LICENSE-2.0
8 |
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
14 | */
15 |
16 | package gmtls
17 |
18 | import "strconv"
19 |
20 | type alert uint8
21 |
22 | const (
23 | // alert level
24 | alertLevelWarning = 1
25 | alertLevelError = 2
26 | )
27 |
28 | const (
29 | alertCloseNotify alert = 0
30 | alertUnexpectedMessage alert = 10
31 | alertBadRecordMAC alert = 20
32 | alertDecryptionFailed alert = 21
33 | alertRecordOverflow alert = 22
34 | alertDecompressionFailure alert = 30
35 | alertHandshakeFailure alert = 40
36 | alertBadCertificate alert = 42
37 | alertUnsupportedCertificate alert = 43
38 | alertCertificateRevoked alert = 44
39 | alertCertificateExpired alert = 45
40 | alertCertificateUnknown alert = 46
41 | alertIllegalParameter alert = 47
42 | alertUnknownCA alert = 48
43 | alertAccessDenied alert = 49
44 | alertDecodeError alert = 50
45 | alertDecryptError alert = 51
46 | alertProtocolVersion alert = 70
47 | alertInsufficientSecurity alert = 71
48 | alertInternalError alert = 80
49 | alertInappropriateFallback alert = 86
50 | alertUserCanceled alert = 90
51 | alertNoRenegotiation alert = 100
52 | alertNoApplicationProtocol alert = 120
53 | //GMT0024
54 | alertUnspporttedSite2Site alert = 200
55 | alertNoArea alert = 201
56 | alertUnspportedAreaType alert = 202
57 | alertBadIBCParam alert = 203
58 | alertUnspportedIBCParam alert = 204
59 | alertIdentityNeed alert = 205
60 | )
61 |
62 | var alertText = map[alert]string{
63 | alertCloseNotify: "close notify",
64 | alertUnexpectedMessage: "unexpected message",
65 | alertBadRecordMAC: "bad record MAC",
66 | alertDecryptionFailed: "decryption failed",
67 | alertRecordOverflow: "record overflow",
68 | alertDecompressionFailure: "decompression failure",
69 | alertHandshakeFailure: "handshake failure",
70 | alertBadCertificate: "bad certificate",
71 | alertUnsupportedCertificate: "unsupported certificate",
72 | alertCertificateRevoked: "revoked certificate",
73 | alertCertificateExpired: "expired certificate",
74 | alertCertificateUnknown: "unknown certificate",
75 | alertIllegalParameter: "illegal parameter",
76 | alertUnknownCA: "unknown certificate authority",
77 | alertAccessDenied: "access denied",
78 | alertDecodeError: "error decoding message",
79 | alertDecryptError: "error decrypting message",
80 | alertProtocolVersion: "protocol version not supported",
81 | alertInsufficientSecurity: "insufficient security level",
82 | alertInternalError: "internal error",
83 | alertInappropriateFallback: "inappropriate fallback",
84 | alertUserCanceled: "user canceled",
85 | alertNoRenegotiation: "no renegotiation",
86 | alertNoApplicationProtocol: "no application protocol",
87 | //GMT0024
88 | alertUnspporttedSite2Site: "不支持site2site",
89 | alertNoArea : "没有保护域",
90 | alertUnspportedAreaType : "不支持的保护域类型",
91 | alertBadIBCParam : "接收到一个无效的ibc公共参数",
92 | alertUnspportedIBCParam : "不支持ibc参数中定义的信息",
93 | alertIdentityNeed : "缺少对方的ibc标识",
94 | }
95 |
96 | func (e alert) String() string {
97 | s, ok := alertText[e]
98 | if ok {
99 | return "tls: " + s
100 | }
101 | return "tls: alert(" + strconv.Itoa(int(e)) + ")"
102 | }
103 |
104 | func (e alert) Error() string {
105 | return e.String()
106 | }
107 |
--------------------------------------------------------------------------------
/sm4/sm4_test.go:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright Suzhou Tongji Fintech Research Institute 2017 All Rights Reserved.
3 | Licensed under the Apache License, Version 2.0 (the "License");
4 | you may not use this file except in compliance with the License.
5 | You may obtain a copy of the License at
6 |
7 | http://www.apache.org/licenses/LICENSE-2.0
8 |
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
14 | */
15 |
16 | package sm4
17 |
18 | import (
19 | "fmt"
20 | "reflect"
21 | "testing"
22 | )
23 |
24 | func TestSM4(t *testing.T) {
25 | key := []byte("1234567890abcdef")
26 |
27 | fmt.Printf("key = %v\n", key)
28 | data := []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10}
29 | err := WriteKeyToPemFile("key.pem", key, nil)
30 | if err != nil {
31 | t.Fatalf("WriteKeyToPem error")
32 | }
33 | key, err = ReadKeyFromPemFile("key.pem", nil)
34 | fmt.Printf("key = %v\n", key)
35 | if err != nil {
36 | t.Fatal(err)
37 | }
38 | fmt.Printf("data = %x\n", data)
39 | ecbMsg, err := Sm4Ecb(key, data, true)
40 | if err != nil {
41 | t.Errorf("sm4 enc error:%s", err)
42 | return
43 | }
44 | fmt.Printf("ecbMsg = %x\n", ecbMsg)
45 | iv := []byte("0000000000000000")
46 | err = SetIV(iv)
47 | fmt.Printf("err = %v\n", err)
48 | ecbDec, err := Sm4Ecb(key, ecbMsg, false)
49 | if err != nil {
50 | t.Errorf("sm4 dec error:%s", err)
51 | return
52 | }
53 | fmt.Printf("ecbDec = %x\n", ecbDec)
54 | if !testCompare(data, ecbDec) {
55 | t.Errorf("sm4 self enc and dec failed")
56 | }
57 | cbcMsg, err := Sm4Cbc(key, data, true)
58 | if err != nil {
59 | t.Errorf("sm4 enc error:%s", err)
60 | }
61 | fmt.Printf("cbcMsg = %x\n", cbcMsg)
62 | cbcDec, err := Sm4Cbc(key, cbcMsg, false)
63 | if err != nil {
64 | t.Errorf("sm4 dec error:%s", err)
65 | return
66 | }
67 | fmt.Printf("cbcDec = %x\n", cbcDec)
68 | if !testCompare(data, cbcDec) {
69 | t.Errorf("sm4 self enc and dec failed")
70 | }
71 |
72 | cbcMsg, err = Sm4CFB(key, data, true)
73 | if err != nil {
74 | t.Errorf("sm4 enc error:%s", err)
75 | }
76 | fmt.Printf("cbcCFB = %x\n", cbcMsg)
77 |
78 | cbcCfb, err := Sm4CFB(key, cbcMsg, false)
79 | if err != nil {
80 | t.Errorf("sm4 dec error:%s", err)
81 | return
82 | }
83 | fmt.Printf("cbcCFB = %x\n", cbcCfb)
84 |
85 | cbcMsg, err = Sm4OFB(key, data, true)
86 | if err != nil {
87 | t.Errorf("sm4 enc error:%s", err)
88 | }
89 | fmt.Printf("cbcOFB = %x\n", cbcMsg)
90 |
91 | cbcOfc, err := Sm4OFB(key, cbcMsg, false)
92 | if err != nil {
93 | t.Errorf("sm4 dec error:%s", err)
94 | return
95 | }
96 | fmt.Printf("cbcOFB = %x\n", cbcOfc)
97 | }
98 |
99 | func BenchmarkSM4(t *testing.B) {
100 | t.ReportAllocs()
101 | key := []byte("1234567890abcdef")
102 | data := []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10}
103 | err := WriteKeyToPemFile("key.pem", key, nil)
104 | if err != nil {
105 | t.Fatalf("WriteKeyToPem error")
106 | }
107 | key, err = ReadKeyFromPemFile("key.pem", nil)
108 | if err != nil {
109 | t.Fatal(err)
110 | }
111 | c, err := NewCipher(key)
112 | if err != nil {
113 | t.Fatal(err)
114 | }
115 |
116 | for i := 0; i < t.N; i++ {
117 | d0 := make([]byte, 16)
118 | c.Encrypt(d0, data)
119 | d1 := make([]byte, 16)
120 | c.Decrypt(d1, d0)
121 | }
122 | }
123 |
124 | func TestErrKeyLen(t *testing.T) {
125 | fmt.Printf("\n--------------test key len------------------")
126 | key := []byte("1234567890abcdefg")
127 | _, err := NewCipher(key)
128 | if err != nil {
129 | fmt.Println("\nError key len !")
130 | }
131 | key = []byte("1234")
132 | _, err = NewCipher(key)
133 | if err != nil {
134 | fmt.Println("Error key len !")
135 | }
136 | fmt.Println("------------------end----------------------")
137 | }
138 |
139 | func testCompare(key1, key2 []byte) bool {
140 | if len(key1) != len(key2) {
141 | return false
142 | }
143 | for i, v := range key1 {
144 | if i == 1 {
145 | fmt.Println("type of v", reflect.TypeOf(v))
146 | }
147 | a := key2[i]
148 | if a != v {
149 | return false
150 | }
151 | }
152 | return true
153 | }
154 |
--------------------------------------------------------------------------------
/gmtls/websvr/websvr_test.go:
--------------------------------------------------------------------------------
1 | package websvr
2 |
3 | import (
4 | "crypto/tls"
5 | "fmt"
6 | "github.com/tjfoc/gmsm/x509"
7 | "io/ioutil"
8 | "log"
9 | "net/http"
10 | "testing"
11 | "time"
12 |
13 | "github.com/tjfoc/gmsm/gmtls"
14 | )
15 |
16 | const (
17 | // rsaCertPath = "certs/rsa_sign.cer"
18 | // rsaKeyPath = "certs/rsa_sign_key.pem"
19 | rsaCacertPath = "certs/rsa_CA.cer"
20 | // sm2SignCertPath = "certs/sm2_sign_cert.cer"
21 | // sm2SignKeyPath = "certs/sm2_sign_key.pem"
22 | // sm2EncCertPath = "certs/sm2_enc_cert.cer"
23 | // sm2EncKeyPath = "certs/sm2_enc_key.pem"
24 | // SM2CaCertPath = "certs/SM2_CA.cer"
25 | sm2UserCertPath = "certs/sm2_auth_cert.cer"
26 | sm2UserKeyPath = "certs/sm2_auth_key.pem"
27 | )
28 |
29 | func ServerRun() {
30 | //config, err := loadRsaConfig()
31 | //config, err := loadSM2Config()
32 | config, err := loadAutoSwitchConfig()
33 | //config, err:=loadAutoSwitchConfigClientAuth()
34 | if err != nil {
35 | panic(err)
36 | }
37 |
38 | ln, err := gmtls.Listen("tcp", ":50052", config)
39 | if err != nil {
40 | log.Println(err)
41 | return
42 | }
43 | defer ln.Close()
44 |
45 | http.HandleFunc("/", func(writer http.ResponseWriter, request *http.Request) {
46 | fmt.Fprintf(writer, "hello\n")
47 | })
48 | fmt.Println(">> HTTP Over [GMSSL/TLS] running...")
49 | err = http.Serve(ln, nil)
50 | if err != nil {
51 | panic(err)
52 | }
53 | }
54 |
55 | func ClientRun() {
56 | var config = tls.Config{
57 | MaxVersion: gmtls.VersionTLS12,
58 | InsecureSkipVerify: true,
59 | }
60 | conn, err := tls.Dial("tcp", "localhost:50052", &config)
61 | if err != nil {
62 | panic(err)
63 | }
64 | defer conn.Close()
65 |
66 | req := []byte("GET / HTTP/1.1\r\n" +
67 | "Host: localhost\r\n" +
68 | "Connection: close\r\n\r\n")
69 | conn.Write(req)
70 |
71 | buff := make([]byte, 1024)
72 | for {
73 | n, _ := conn.Read(buff)
74 | if n <= 0 {
75 | break
76 | } else {
77 | fmt.Printf("%s", buff[0:n])
78 | }
79 | }
80 | fmt.Println(">> RSA TLS [PASS]")
81 | end <- true
82 | }
83 |
84 | func gmClientRun() {
85 |
86 | // 信任的根证书
87 | certPool := x509.NewCertPool()
88 | cacert, err := ioutil.ReadFile(SM2CaCertPath)
89 | if err != nil {
90 | log.Fatal(err)
91 | }
92 | certPool.AppendCertsFromPEM(cacert)
93 | cert, err := gmtls.LoadX509KeyPair(sm2UserCertPath, sm2UserKeyPath)
94 |
95 | config := &gmtls.Config{
96 | GMSupport: &gmtls.GMSupport{},
97 | RootCAs: certPool,
98 | Certificates: []gmtls.Certificate{cert},
99 | }
100 |
101 | conn, err := gmtls.Dial("tcp", "localhost:50052", config)
102 | if err != nil {
103 | panic(err)
104 | }
105 | defer conn.Close()
106 |
107 | req := []byte("GET / HTTP/1.1\r\n" +
108 | "Host: localhost\r\n" +
109 | "Connection: close\r\n\r\n")
110 | _, _ = conn.Write(req)
111 | buff := make([]byte, 1024)
112 | for {
113 | n, _ := conn.Read(buff)
114 | if n <= 0 {
115 | break
116 | } else {
117 | fmt.Printf("%s", buff[0:n])
118 | }
119 | }
120 | fmt.Println(">> SM2_SM4_CBC_SM3 suite [PASS]")
121 | end <- true
122 | }
123 |
124 | // gmGCMClientRun GCM模式测试
125 | func gmGCMClientRun() {
126 |
127 | // 信任的根证书
128 | certPool := x509.NewCertPool()
129 | cacert, err := ioutil.ReadFile(SM2CaCertPath)
130 | if err != nil {
131 | log.Fatal(err)
132 | }
133 | certPool.AppendCertsFromPEM(cacert)
134 | cert, err := gmtls.LoadX509KeyPair(sm2UserCertPath, sm2UserKeyPath)
135 |
136 | config := &gmtls.Config{
137 | GMSupport: &gmtls.GMSupport{},
138 | RootCAs: certPool,
139 | Certificates: []gmtls.Certificate{cert},
140 | CipherSuites: []uint16{gmtls.GMTLS_ECC_SM4_GCM_SM3},
141 | }
142 |
143 | conn, err := gmtls.Dial("tcp", "localhost:50052", config)
144 | if err != nil {
145 | panic(err)
146 | }
147 | defer conn.Close()
148 |
149 | req := []byte("GET / HTTP/1.1\r\n" +
150 | "Host: localhost\r\n" +
151 | "Connection: close\r\n\r\n")
152 | _, _ = conn.Write(req)
153 | buff := make([]byte, 1024)
154 | for {
155 | n, _ := conn.Read(buff)
156 | if n <= 0 {
157 | break
158 | } else {
159 | fmt.Printf("%s", buff[0:n])
160 | }
161 | }
162 | fmt.Println(">> SM2_SM4_GCM_SM3 suite [PASS]")
163 | end <- true
164 | }
165 |
166 | var end chan bool
167 |
168 | func Test_tls(t *testing.T) {
169 | end = make(chan bool, 64)
170 | go ServerRun()
171 | time.Sleep(time.Second)
172 | go ClientRun()
173 | <-end
174 | go gmClientRun()
175 | <-end
176 | go gmGCMClientRun()
177 | <-end
178 |
179 | }
180 |
--------------------------------------------------------------------------------
/x509/pkcs7_test.go:
--------------------------------------------------------------------------------
1 | package x509
2 |
3 | import (
4 | "crypto/x509/pkix"
5 | "encoding/asn1"
6 | "math/big"
7 | "net"
8 | "testing"
9 | "time"
10 |
11 | "github.com/tjfoc/gmsm/sm2"
12 | )
13 |
14 | func TestPKCS7SM2(t *testing.T) {
15 | priv, err := sm2.GenerateKey(nil) // 生成密钥对
16 | if err != nil {
17 | t.Fatal(err)
18 | }
19 | privPem, err := WritePrivateKeyToPem(priv, nil) // 生成密钥文件
20 | if err != nil {
21 | t.Fatal(err)
22 | }
23 | pubKey, _ := priv.Public().(*sm2.PublicKey)
24 | pubkeyPem, err := WritePublicKeyToPem(pubKey) // 生成公钥文件
25 | privKey, err := ReadPrivateKeyFromPem(privPem, nil) // 读取密钥
26 | if err != nil {
27 | t.Fatal(err)
28 | }
29 | pubKey, err = ReadPublicKeyFromPem(pubkeyPem) // 读取公钥
30 | if err != nil {
31 | t.Fatal(err)
32 | }
33 | templateReq := CertificateRequest{
34 | Subject: pkix.Name{
35 | CommonName: "test.example.com",
36 | Organization: []string{"Test"},
37 | },
38 | // SignatureAlgorithm: ECDSAWithSHA256,
39 | SignatureAlgorithm: SM2WithSM3,
40 | }
41 | reqPem, err := CreateCertificateRequestToPem(&templateReq, privKey)
42 | if err != nil {
43 | t.Fatal(err)
44 | }
45 | req, err := ReadCertificateRequestFromPem(reqPem)
46 | if err != nil {
47 | t.Fatal(err)
48 | }
49 | err = req.CheckSignature()
50 | if err != nil {
51 | t.Fatalf("Request CheckSignature error:%v", err)
52 | } else {
53 | t.Log("CheckSignature ok")
54 | }
55 | testExtKeyUsage := []ExtKeyUsage{ExtKeyUsageClientAuth, ExtKeyUsageServerAuth}
56 | testUnknownExtKeyUsage := []asn1.ObjectIdentifier{[]int{1, 2, 3}, []int{2, 59, 1}}
57 | extraExtensionData := []byte("extra extension")
58 | commonName := "test.example.com"
59 | template := Certificate{
60 | // SerialNumber is negative to ensure that negative
61 | // values are parsed. This is due to the prevalence of
62 | // buggy code that produces certificates with negative
63 | // serial numbers.
64 | SerialNumber: big.NewInt(-1),
65 | Subject: pkix.Name{
66 | CommonName: commonName,
67 | Organization: []string{"TEST"},
68 | Country: []string{"China"},
69 | ExtraNames: []pkix.AttributeTypeAndValue{
70 | {
71 | Type: []int{2, 5, 4, 42},
72 | Value: "Gopher",
73 | },
74 | // This should override the Country, above.
75 | {
76 | Type: []int{2, 5, 4, 6},
77 | Value: "NL",
78 | },
79 | },
80 | },
81 | NotBefore: time.Now(),
82 | NotAfter: time.Date(2021, time.October, 10, 12, 1, 1, 1, time.UTC),
83 |
84 | // SignatureAlgorithm: ECDSAWithSHA256,
85 | SignatureAlgorithm: SM2WithSM3,
86 |
87 | SubjectKeyId: []byte{1, 2, 3, 4},
88 | KeyUsage: KeyUsageCertSign,
89 |
90 | ExtKeyUsage: testExtKeyUsage,
91 | UnknownExtKeyUsage: testUnknownExtKeyUsage,
92 |
93 | BasicConstraintsValid: true,
94 | IsCA: true,
95 |
96 | OCSPServer: []string{"http://ocsp.example.com"},
97 | IssuingCertificateURL: []string{"http://crt.example.com/ca1.crt"},
98 |
99 | DNSNames: []string{"test.example.com"},
100 | EmailAddresses: []string{"gopher@golang.org"},
101 | IPAddresses: []net.IP{net.IPv4(127, 0, 0, 1).To4(), net.ParseIP("2001:4860:0:2001::68")},
102 |
103 | PolicyIdentifiers: []asn1.ObjectIdentifier{[]int{1, 2, 3}},
104 | PermittedDNSDomains: []string{".example.com", "example.com"},
105 |
106 | CRLDistributionPoints: []string{"http://crl1.example.com/ca1.crl", "http://crl2.example.com/ca1.crl"},
107 |
108 | ExtraExtensions: []pkix.Extension{
109 | {
110 | Id: []int{1, 2, 3, 4},
111 | Value: extraExtensionData,
112 | },
113 | // This extension should override the SubjectKeyId, above.
114 | {
115 | Id: oidExtensionSubjectKeyId,
116 | Critical: false,
117 | Value: []byte{0x04, 0x04, 4, 3, 2, 1},
118 | },
119 | },
120 | }
121 | pubKey, _ = priv.Public().(*sm2.PublicKey)
122 | certpem, err := CreateCertificateToPem(&template, &template, pubKey, privKey)
123 | if err != nil {
124 | t.Fatal("failed to create cert file")
125 | }
126 | cert, err := ReadCertificateFromPem(certpem)
127 | if err != nil {
128 | t.Fatal("failed to read cert file")
129 | }
130 | err = cert.CheckSignature(cert.SignatureAlgorithm, cert.RawTBSCertificate, cert.Signature)
131 | if err != nil {
132 | t.Fatal(err)
133 | } else {
134 | t.Log("CheckSignature ok")
135 | }
136 |
137 | content := []byte("this is test")
138 | data, err := PKCS7EncryptSM2(content, []*Certificate{cert}, sm2.C1C3C2)
139 | if err != nil {
140 | t.Fatal("failed to PKCS7Encrypt ")
141 | }
142 | pk7Data, err := ParsePKCS7(data)
143 |
144 | if err != nil {
145 | t.Fatal("failed to ParsePKCS7 ")
146 | }
147 | decryptData, err := pk7Data.DecryptSM2(cert, priv, sm2.C1C3C2)
148 | if err != nil {
149 | t.Fatal("failed to PKCS7Decrypt ")
150 | }
151 | t.Log("decrypt success! data: ", string(decryptData))
152 | }
153 |
--------------------------------------------------------------------------------
/gmtls/websvr/websvr.go:
--------------------------------------------------------------------------------
1 | package websvr
2 |
3 | import (
4 | "crypto/tls"
5 | x "crypto/x509"
6 | "github.com/tjfoc/gmsm/gmtls"
7 | "github.com/tjfoc/gmsm/x509"
8 | "io/ioutil"
9 | )
10 |
11 | const (
12 | rsaCertPath = "./certs/rsa_sign.cer"
13 | rsaKeyPath = "./certs/rsa_sign_key.pem"
14 | RSACaCertPath = "./certs/RSA_CA.cer"
15 | RSAAuthCertPath = "./certs/rsa_auth_cert.cer"
16 | RSAAuthKeyPath = "./certs/rsa_auth_key.pem"
17 | SM2CaCertPath = "./certs/SM2_CA.cer"
18 | SM2AuthCertPath = "./certs/sm2_auth_cert.cer"
19 | SM2AuthKeyPath = "./certs/sm2_auth_key.pem"
20 | sm2SignCertPath = "./certs/sm2_sign_cert.cer"
21 | sm2SignKeyPath = "./certs/sm2_sign_key.pem"
22 | sm2EncCertPath = "./certs/sm2_enc_cert.cer"
23 | sm2EncKeyPath = "./certs/sm2_enc_key.pem"
24 | )
25 |
26 | // RSA配置
27 | func loadRsaConfig() (*gmtls.Config, error) {
28 | cert, err := gmtls.LoadX509KeyPair(rsaCertPath, rsaKeyPath)
29 | if err != nil {
30 | return nil, err
31 | }
32 | return &gmtls.Config{Certificates: []gmtls.Certificate{cert}}, nil
33 | }
34 |
35 | // SM2配置
36 | func loadSM2Config() (*gmtls.Config, error) {
37 | sigCert, err := gmtls.LoadX509KeyPair(sm2SignCertPath, sm2SignKeyPath)
38 | if err != nil {
39 | return nil, err
40 | }
41 | encCert, err := gmtls.LoadX509KeyPair(sm2EncCertPath, sm2EncKeyPath)
42 | if err != nil {
43 | return nil, err
44 | }
45 | return &gmtls.Config{
46 | GMSupport: &gmtls.GMSupport{},
47 | Certificates: []gmtls.Certificate{sigCert, encCert},
48 | }, nil
49 | }
50 |
51 | // 切换GMSSL/TSL
52 | func loadAutoSwitchConfig() (*gmtls.Config, error) {
53 | rsaKeypair, err := gmtls.LoadX509KeyPair(rsaCertPath, rsaKeyPath)
54 | if err != nil {
55 | return nil, err
56 | }
57 | sigCert, err := gmtls.LoadX509KeyPair(sm2SignCertPath, sm2SignKeyPath)
58 | if err != nil {
59 | return nil, err
60 | }
61 | encCert, err := gmtls.LoadX509KeyPair(sm2EncCertPath, sm2EncKeyPath)
62 | if err != nil {
63 | return nil, err
64 |
65 | }
66 | return gmtls.NewBasicAutoSwitchConfig(&sigCert, &encCert, &rsaKeypair)
67 | }
68 |
69 | // 双向身份认证 服务端配置
70 | func loadServerMutualTLCPAuthConfig() (*gmtls.Config, error) {
71 | // 签名密钥对/证书 和 加密密钥对/证书
72 | sigCert, err := gmtls.LoadX509KeyPair(sm2SignCertPath, sm2SignKeyPath)
73 | if err != nil {
74 | return nil, err
75 | }
76 | encCert, err := gmtls.LoadX509KeyPair(sm2EncCertPath, sm2EncKeyPath)
77 | if err != nil {
78 | return nil, err
79 |
80 | }
81 |
82 | // 信任的根证书
83 | certPool := x509.NewCertPool()
84 | cacert, err := ioutil.ReadFile(SM2CaCertPath)
85 | if err != nil {
86 | return nil, err
87 | }
88 | certPool.AppendCertsFromPEM(cacert)
89 |
90 | return &gmtls.Config{
91 | GMSupport: gmtls.NewGMSupport(),
92 | Certificates: []gmtls.Certificate{sigCert, encCert},
93 | ClientCAs: certPool,
94 | ClientAuth: gmtls.RequireAndVerifyClientCert,
95 | }, nil
96 | }
97 |
98 | // 要求客户端身份认证
99 | func loadAutoSwitchConfigClientAuth() (*gmtls.Config, error) {
100 | config, err := loadAutoSwitchConfig()
101 | if err != nil {
102 | return nil, err
103 | }
104 | // 设置需要客户端证书请求,标识需要进行客户端的身份认证
105 | config.ClientAuth = gmtls.RequireAndVerifyClientCert
106 | return config, nil
107 | }
108 |
109 | // 获取 客户端服务端双向身份认证 配置
110 | func bothAuthConfig() (*gmtls.Config, error) {
111 | // 信任的根证书
112 | certPool := x509.NewCertPool()
113 | cacert, err := ioutil.ReadFile(SM2CaCertPath)
114 | if err != nil {
115 | return nil, err
116 | }
117 | certPool.AppendCertsFromPEM(cacert)
118 | authKeypair, err := gmtls.LoadX509KeyPair(SM2AuthCertPath, SM2AuthKeyPath)
119 | if err != nil {
120 | return nil, err
121 | }
122 | return &gmtls.Config{
123 | GMSupport: &gmtls.GMSupport{},
124 | RootCAs: certPool,
125 | Certificates: []gmtls.Certificate{authKeypair},
126 | InsecureSkipVerify: false,
127 | }, nil
128 |
129 | }
130 |
131 | // 获取 单向身份认证(只认证服务端) 配置
132 | func singleSideAuthConfig() (*gmtls.Config, error) {
133 | // 信任的根证书
134 | certPool := x509.NewCertPool()
135 | cacert, err := ioutil.ReadFile(SM2CaCertPath)
136 | if err != nil {
137 | return nil, err
138 | }
139 | certPool.AppendCertsFromPEM(cacert)
140 |
141 | return &gmtls.Config{
142 | GMSupport: &gmtls.GMSupport{},
143 | RootCAs: certPool,
144 | }, nil
145 | }
146 |
147 | // 获取 客户端服务端双向身份认证 配置
148 | func rsaBothAuthConfig() (*tls.Config, error) {
149 | // 信任的根证书
150 | certPool := x.NewCertPool()
151 | cacert, err := ioutil.ReadFile(RSACaCertPath)
152 | if err != nil {
153 | return nil, err
154 | }
155 | certPool.AppendCertsFromPEM(cacert)
156 | authKeypair, err := tls.LoadX509KeyPair(RSAAuthCertPath, RSAAuthKeyPath)
157 | if err != nil {
158 | return nil, err
159 | }
160 | return &tls.Config{
161 | MaxVersion: tls.VersionTLS12,
162 | RootCAs: certPool,
163 | Certificates: []tls.Certificate{authKeypair},
164 | InsecureSkipVerify: false,
165 | }, nil
166 |
167 | }
168 |
169 | // 获取 单向身份认证(只认证服务端) 配置
170 | func rsaSingleSideAuthConfig() (*tls.Config, error) {
171 | // 信任的根证书
172 | certPool := x.NewCertPool()
173 | cacert, err := ioutil.ReadFile(RSACaCertPath)
174 | if err != nil {
175 | return nil, err
176 | }
177 | certPool.AppendCertsFromPEM(cacert)
178 |
179 | return &tls.Config{
180 | MaxVersion: tls.VersionTLS12,
181 | RootCAs: certPool,
182 | }, nil
183 | }
184 |
--------------------------------------------------------------------------------
/gmtls/auth.go:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright Suzhou Tongji Fintech Research Institute 2017 All Rights Reserved.
3 | Licensed under the Apache License, Version 2.0 (the "License");
4 | you may not use this file except in compliance with the License.
5 | You may obtain a copy of the License at
6 |
7 | http://www.apache.org/licenses/LICENSE-2.0
8 |
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
14 | */
15 |
16 | package gmtls
17 |
18 | import (
19 | "crypto"
20 | "crypto/ecdsa"
21 | "crypto/rsa"
22 | "encoding/asn1"
23 | "errors"
24 | "fmt"
25 |
26 | "github.com/tjfoc/gmsm/sm2"
27 | )
28 |
29 | // pickSignatureAlgorithm selects a signature algorithm that is compatible with
30 | // the given public key and the list of algorithms from the peer and this side.
31 | // The lists of signature algorithms (peerSigAlgs and ourSigAlgs) are ignored
32 | // for tlsVersion < VersionTLS12.
33 | //
34 | // The returned SignatureScheme codepoint is only meaningful for TLS 1.2,
35 | // previous TLS versions have a fixed hash function.
36 | func pickSignatureAlgorithm(pubkey crypto.PublicKey, peerSigAlgs, ourSigAlgs []SignatureScheme, tlsVersion uint16) (sigAlg SignatureScheme, sigType uint8, hashFunc crypto.Hash, err error) {
37 | if tlsVersion < VersionTLS12 || len(peerSigAlgs) == 0 {
38 | // For TLS 1.1 and before, the signature algorithm could not be
39 | // negotiated and the hash is fixed based on the signature type.
40 | // For TLS 1.2, if the client didn't send signature_algorithms
41 | // extension then we can assume that it supports SHA1. See
42 | // https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1
43 | switch pubkey.(type) {
44 | case *rsa.PublicKey:
45 | if tlsVersion < VersionTLS12 {
46 | return 0, signaturePKCS1v15, crypto.MD5SHA1, nil
47 | } else {
48 | return PKCS1WithSHA1, signaturePKCS1v15, crypto.SHA1, nil
49 | }
50 | case *ecdsa.PublicKey:
51 | return ECDSAWithSHA1, signatureECDSA, crypto.SHA1, nil
52 | case *sm2.PublicKey:
53 | return SM2WITHSM3, signatureSM2, crypto.SHA1, nil
54 | default:
55 | return 0, 0, 0, fmt.Errorf("tls: unsupported public key: %T", pubkey)
56 | }
57 | }
58 | for _, sigAlg := range peerSigAlgs {
59 | if !isSupportedSignatureAlgorithm(sigAlg, ourSigAlgs) {
60 | continue
61 | }
62 | hashAlg, err := lookupTLSHash(sigAlg)
63 | if err != nil {
64 | panic("tls: supported signature algorithm has an unknown hash function")
65 | }
66 | sigType := signatureFromSignatureScheme(sigAlg)
67 | switch pubkey.(type) {
68 | case *rsa.PublicKey:
69 | if sigType == signaturePKCS1v15 || sigType == signatureRSAPSS {
70 | return sigAlg, sigType, hashAlg, nil
71 | }
72 | case *ecdsa.PublicKey:
73 | if sigType == signatureECDSA {
74 | return sigAlg, sigType, hashAlg, nil
75 | }
76 | case *sm2.PublicKey:
77 | if sigType == signatureECDSA {
78 | return sigAlg, sigType, hashAlg, nil
79 | }
80 | default:
81 | return 0, 0, 0, fmt.Errorf("tls: unsupported public key: %T", pubkey)
82 | }
83 | }
84 | return 0, 0, 0, errors.New("tls: peer doesn't support any common signature algorithms")
85 | }
86 |
87 | // verifyHandshakeSignature verifies a signature against pre-hashed handshake
88 | // contents.
89 | func verifyHandshakeSignature(sigType uint8, pubkey crypto.PublicKey, hashFunc crypto.Hash, digest, sig []byte) error {
90 | switch sigType {
91 | case signatureECDSA:
92 | pubKey, ok := pubkey.(*ecdsa.PublicKey)
93 | if !ok {
94 | return errors.New("tls: ECDSA signing requires a ECDSA public key")
95 | }
96 | ecdsaSig := new(ecdsaSignature)
97 | if _, err := asn1.Unmarshal(sig, ecdsaSig); err != nil {
98 | return err
99 | }
100 | if ecdsaSig.R.Sign() <= 0 || ecdsaSig.S.Sign() <= 0 {
101 | return errors.New("tls: ECDSA signature contained zero or negative values")
102 | }
103 | if pubKey.Curve == sm2.P256Sm2() {
104 | sm2Public := sm2.PublicKey{
105 | Curve: pubKey.Curve,
106 | X: pubKey.X,
107 | Y: pubKey.Y,
108 | }
109 | if !sm2Public.Verify(digest, sig) {
110 | return errors.New("tls: SM2 verification failure")
111 | }
112 | } else if !ecdsa.Verify(pubKey, digest, ecdsaSig.R, ecdsaSig.S) {
113 | return errors.New("tls: ECDSA verification failure")
114 | }
115 | case signaturePKCS1v15:
116 | pubKey, ok := pubkey.(*rsa.PublicKey)
117 | if !ok {
118 | return errors.New("tls: RSA signing requires a RSA public key")
119 | }
120 | if err := rsa.VerifyPKCS1v15(pubKey, hashFunc, digest, sig); err != nil {
121 | return err
122 | }
123 | case signatureRSAPSS:
124 | pubKey, ok := pubkey.(*rsa.PublicKey)
125 | if !ok {
126 | return errors.New("tls: RSA signing requires a RSA public key")
127 | }
128 | signOpts := &rsa.PSSOptions{SaltLength: rsa.PSSSaltLengthEqualsHash}
129 | if err := rsa.VerifyPSS(pubKey, hashFunc, digest, sig, signOpts); err != nil {
130 | return err
131 | }
132 | case signatureSM2:
133 | pubKey, ok := pubkey.(*sm2.PublicKey)
134 | if !ok {
135 | return errors.New("tls: SM2 signing requires a SM2 public key")
136 | }
137 | if ok := pubKey.Verify(digest, sig); !ok {
138 | return errors.New("verify sm2 signature error")
139 | }
140 | default:
141 | return errors.New("tls: unknown signature algorithm")
142 | }
143 | return nil
144 | }
145 |
--------------------------------------------------------------------------------
/gmtls/gmcredentials/echo/echo.pb.go:
--------------------------------------------------------------------------------
1 | // Code generated by protoc-gen-go. DO NOT EDIT.
2 | // source: echo.proto
3 |
4 | /*
5 | Package echo is a generated protocol buffer package.
6 |
7 | It is generated from these files:
8 | echo.proto
9 |
10 | It has these top-level messages:
11 | EchoRequest
12 | EchoResponse
13 | */
14 | package echo
15 |
16 | import proto "github.com/golang/protobuf/proto"
17 | import fmt "fmt"
18 | import math "math"
19 |
20 | import (
21 | context "golang.org/x/net/context"
22 | grpc "google.golang.org/grpc"
23 | )
24 |
25 | // Reference imports to suppress errors if they are not otherwise used.
26 | var _ = proto.Marshal
27 | var _ = fmt.Errorf
28 | var _ = math.Inf
29 |
30 | // This is a compile-time assertion to ensure that this generated file
31 | // is compatible with the proto package it is being compiled against.
32 | // A compilation error at this line likely means your copy of the
33 | // proto package needs to be updated.
34 | const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
35 |
36 | type EchoRequest struct {
37 | Req string `protobuf:"bytes,1,opt,name=req" json:"req,omitempty"`
38 | }
39 |
40 | func (m *EchoRequest) Reset() { *m = EchoRequest{} }
41 | func (m *EchoRequest) String() string { return proto.CompactTextString(m) }
42 | func (*EchoRequest) ProtoMessage() {}
43 | func (*EchoRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
44 |
45 | func (m *EchoRequest) GetReq() string {
46 | if m != nil {
47 | return m.Req
48 | }
49 | return ""
50 | }
51 |
52 | type EchoResponse struct {
53 | Result string `protobuf:"bytes,1,opt,name=result" json:"result,omitempty"`
54 | }
55 |
56 | func (m *EchoResponse) Reset() { *m = EchoResponse{} }
57 | func (m *EchoResponse) String() string { return proto.CompactTextString(m) }
58 | func (*EchoResponse) ProtoMessage() {}
59 | func (*EchoResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} }
60 |
61 | func (m *EchoResponse) GetResult() string {
62 | if m != nil {
63 | return m.Result
64 | }
65 | return ""
66 | }
67 |
68 | func init() {
69 | proto.RegisterType((*EchoRequest)(nil), "echo.EchoRequest")
70 | proto.RegisterType((*EchoResponse)(nil), "echo.EchoResponse")
71 | }
72 |
73 | // Reference imports to suppress errors if they are not otherwise used.
74 | var _ context.Context
75 | var _ grpc.ClientConn
76 |
77 | // This is a compile-time assertion to ensure that this generated file
78 | // is compatible with the grpc package it is being compiled against.
79 | const _ = grpc.SupportPackageIsVersion4
80 |
81 | // Client API for Echo service
82 |
83 | type EchoClient interface {
84 | Echo(ctx context.Context, in *EchoRequest, opts ...grpc.CallOption) (*EchoResponse, error)
85 | }
86 |
87 | type echoClient struct {
88 | cc *grpc.ClientConn
89 | }
90 |
91 | func NewEchoClient(cc *grpc.ClientConn) EchoClient {
92 | return &echoClient{cc}
93 | }
94 |
95 | func (c *echoClient) Echo(ctx context.Context, in *EchoRequest, opts ...grpc.CallOption) (*EchoResponse, error) {
96 | out := new(EchoResponse)
97 | err := grpc.Invoke(ctx, "/echo.Echo/Echo", in, out, c.cc, opts...)
98 | if err != nil {
99 | return nil, err
100 | }
101 | return out, nil
102 | }
103 |
104 | // Server API for Echo service
105 |
106 | type EchoServer interface {
107 | Echo(context.Context, *EchoRequest) (*EchoResponse, error)
108 | }
109 |
110 | func RegisterEchoServer(s *grpc.Server, srv EchoServer) {
111 | s.RegisterService(&_Echo_serviceDesc, srv)
112 | }
113 |
114 | func _Echo_Echo_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
115 | in := new(EchoRequest)
116 | if err := dec(in); err != nil {
117 | return nil, err
118 | }
119 | if interceptor == nil {
120 | return srv.(EchoServer).Echo(ctx, in)
121 | }
122 | info := &grpc.UnaryServerInfo{
123 | Server: srv,
124 | FullMethod: "/echo.Echo/Echo",
125 | }
126 | handler := func(ctx context.Context, req interface{}) (interface{}, error) {
127 | return srv.(EchoServer).Echo(ctx, req.(*EchoRequest))
128 | }
129 | return interceptor(ctx, in, info, handler)
130 | }
131 |
132 | var _Echo_serviceDesc = grpc.ServiceDesc{
133 | ServiceName: "echo.Echo",
134 | HandlerType: (*EchoServer)(nil),
135 | Methods: []grpc.MethodDesc{
136 | {
137 | MethodName: "Echo",
138 | Handler: _Echo_Echo_Handler,
139 | },
140 | },
141 | Streams: []grpc.StreamDesc{},
142 | Metadata: "echo.proto",
143 | }
144 |
145 | func init() { proto.RegisterFile("echo.proto", fileDescriptor0) }
146 |
147 | var fileDescriptor0 = []byte{
148 | // 126 bytes of a gzipped FileDescriptorProto
149 | 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x4a, 0x4d, 0xce, 0xc8,
150 | 0xd7, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x01, 0xb1, 0x95, 0xe4, 0xb9, 0xb8, 0x5d, 0x93,
151 | 0x33, 0xf2, 0x83, 0x52, 0x0b, 0x4b, 0x53, 0x8b, 0x4b, 0x84, 0x04, 0xb8, 0x98, 0x8b, 0x52, 0x0b,
152 | 0x25, 0x18, 0x15, 0x18, 0x35, 0x38, 0x83, 0x40, 0x4c, 0x25, 0x35, 0x2e, 0x1e, 0x88, 0x82, 0xe2,
153 | 0x82, 0xfc, 0xbc, 0xe2, 0x54, 0x21, 0x31, 0x2e, 0xb6, 0xa2, 0xd4, 0xe2, 0xd2, 0x9c, 0x12, 0xa8,
154 | 0x22, 0x28, 0xcf, 0xc8, 0x9c, 0x8b, 0x05, 0xa4, 0x4e, 0x48, 0x1f, 0x4a, 0x0b, 0xea, 0x81, 0xed,
155 | 0x42, 0x32, 0x5c, 0x4a, 0x08, 0x59, 0x08, 0x62, 0x9c, 0x12, 0x43, 0x12, 0x1b, 0xd8, 0x39, 0xc6,
156 | 0x80, 0x00, 0x00, 0x00, 0xff, 0xff, 0x1b, 0x48, 0x20, 0x0f, 0x9c, 0x00, 0x00, 0x00,
157 | }
158 |
--------------------------------------------------------------------------------
/pkcs12/crypto.go:
--------------------------------------------------------------------------------
1 | // Copyright 2015 The Go Authors. All rights reserved.
2 | // Use of this source code is governed by a BSD-style
3 | // license that can be found in the LICENSE file.
4 |
5 | package pkcs12
6 |
7 | import (
8 | "bytes"
9 | "crypto/cipher"
10 | "crypto/des"
11 | "crypto/x509/pkix"
12 | "encoding/asn1"
13 | "errors"
14 | )
15 |
16 | var (
17 | oidPBEWithSHAAnd3KeyTripleDESCBC = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 12, 1, 3})
18 | oidPBEWithSHAAnd40BitRC2CBC = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 12, 1, 6})
19 | )
20 |
21 | // pbeCipher is an abstraction of a PKCS#12 cipher.
22 | type pbeCipher interface {
23 | // create returns a cipher.Block given a key.
24 | create(key []byte) (cipher.Block, error)
25 | // deriveKey returns a key derived from the given password and salt.
26 | deriveKey(salt, password []byte, iterations int) []byte
27 | // deriveKey returns an IV derived from the given password and salt.
28 | deriveIV(salt, password []byte, iterations int) []byte
29 | }
30 |
31 | type shaWithTripleDESCBC struct{}
32 |
33 | func (shaWithTripleDESCBC) create(key []byte) (cipher.Block, error) {
34 | return des.NewTripleDESCipher(key)
35 | }
36 |
37 | func (shaWithTripleDESCBC) deriveKey(salt, password []byte, iterations int) []byte {
38 | return pbkdf(sha1Sum, 20, 64, salt, password, iterations, 1, 24)
39 | }
40 |
41 | func (shaWithTripleDESCBC) deriveIV(salt, password []byte, iterations int) []byte {
42 | return pbkdf(sha1Sum, 20, 64, salt, password, iterations, 2, 8)
43 | }
44 |
45 | type shaWith40BitRC2CBC struct{}
46 |
47 | func (shaWith40BitRC2CBC) create(key []byte) (cipher.Block, error) {
48 | return New(key, len(key)*8)
49 | }
50 |
51 | func (shaWith40BitRC2CBC) deriveKey(salt, password []byte, iterations int) []byte {
52 | return pbkdf(sha1Sum, 20, 64, salt, password, iterations, 1, 5)
53 | }
54 |
55 | func (shaWith40BitRC2CBC) deriveIV(salt, password []byte, iterations int) []byte {
56 | return pbkdf(sha1Sum, 20, 64, salt, password, iterations, 2, 8)
57 | }
58 |
59 | type pbeParams struct {
60 | Salt []byte
61 | Iterations int
62 | }
63 |
64 | func pbeCipherFor(algorithm pkix.AlgorithmIdentifier, password []byte) (cipher.Block, []byte, error) {
65 | var cipherType pbeCipher
66 |
67 | switch {
68 | case algorithm.Algorithm.Equal(oidPBEWithSHAAnd3KeyTripleDESCBC):
69 | cipherType = shaWithTripleDESCBC{}
70 | case algorithm.Algorithm.Equal(oidPBEWithSHAAnd40BitRC2CBC):
71 | cipherType = shaWith40BitRC2CBC{}
72 | default:
73 | return nil, nil, NotImplementedError("algorithm " + algorithm.Algorithm.String() + " is not supported")
74 | }
75 |
76 | var params pbeParams
77 | if err := unmarshal(algorithm.Parameters.FullBytes, ¶ms); err != nil {
78 | return nil, nil, err
79 | }
80 |
81 | key := cipherType.deriveKey(params.Salt, password, params.Iterations)
82 | iv := cipherType.deriveIV(params.Salt, password, params.Iterations)
83 |
84 | block, err := cipherType.create(key)
85 | if err != nil {
86 | return nil, nil, err
87 | }
88 |
89 | return block, iv, nil
90 | }
91 |
92 | func pbDecrypterFor(algorithm pkix.AlgorithmIdentifier, password []byte) (cipher.BlockMode, int, error) {
93 | block, iv, err := pbeCipherFor(algorithm, password)
94 | if err != nil {
95 | return nil, 0, err
96 | }
97 |
98 | return cipher.NewCBCDecrypter(block, iv), block.BlockSize(), nil
99 | }
100 |
101 | func pbDecrypt(info decryptable, password []byte) (decrypted []byte, err error) {
102 | cbc, blockSize, err := pbDecrypterFor(info.Algorithm(), password)
103 | if err != nil {
104 | return nil, err
105 | }
106 |
107 | encrypted := info.Data()
108 | if len(encrypted) == 0 {
109 | return nil, errors.New("go-pkcs12: empty encrypted data")
110 | }
111 | if len(encrypted)%blockSize != 0 {
112 | return nil, errors.New("go-pkcs12: input is not a multiple of the block size")
113 | }
114 | decrypted = make([]byte, len(encrypted))
115 | cbc.CryptBlocks(decrypted, encrypted)
116 |
117 | psLen := int(decrypted[len(decrypted)-1])
118 | if psLen == 0 || psLen > blockSize {
119 | return nil, ErrDecryption
120 | }
121 |
122 | if len(decrypted) < psLen {
123 | return nil, ErrDecryption
124 | }
125 | ps := decrypted[len(decrypted)-psLen:]
126 | decrypted = decrypted[:len(decrypted)-psLen]
127 | if bytes.Compare(ps, bytes.Repeat([]byte{byte(psLen)}, psLen)) != 0 {
128 | return nil, ErrDecryption
129 | }
130 |
131 | return
132 | }
133 |
134 | // decryptable abstracts a object that contains ciphertext.
135 | type decryptable interface {
136 | Algorithm() pkix.AlgorithmIdentifier
137 | Data() []byte
138 | }
139 |
140 | func pbEncrypterFor(algorithm pkix.AlgorithmIdentifier, password []byte) (cipher.BlockMode, int, error) {
141 | block, iv, err := pbeCipherFor(algorithm, password)
142 | if err != nil {
143 | return nil, 0, err
144 | }
145 |
146 | return cipher.NewCBCEncrypter(block, iv), block.BlockSize(), nil
147 | }
148 |
149 | func pbEncrypt(info encryptable, decrypted []byte, password []byte) error {
150 | cbc, blockSize, err := pbEncrypterFor(info.Algorithm(), password)
151 | if err != nil {
152 | return err
153 | }
154 |
155 | psLen := blockSize - len(decrypted)%blockSize
156 | encrypted := make([]byte, len(decrypted)+psLen)
157 | copy(encrypted[:len(decrypted)], decrypted)
158 | copy(encrypted[len(decrypted):], bytes.Repeat([]byte{byte(psLen)}, psLen))
159 | cbc.CryptBlocks(encrypted, encrypted)
160 |
161 | info.SetData(encrypted)
162 |
163 | return nil
164 | }
165 |
166 | // encryptable abstracts a object that contains ciphertext.
167 | type encryptable interface {
168 | Algorithm() pkix.AlgorithmIdentifier
169 | SetData([]byte)
170 | }
171 |
--------------------------------------------------------------------------------
/sm2/sm2_test.go:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright Suzhou Tongji Fintech Research Institute 2017 All Rights Reserved.
3 | Licensed under the Apache License, Version 2.0 (the "License");
4 | you may not use this file except in compliance with the License.
5 | You may obtain a copy of the License at
6 |
7 | http://www.apache.org/licenses/LICENSE-2.0
8 |
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
14 | */
15 |
16 | package sm2
17 |
18 | import (
19 | "bytes"
20 | "crypto/rand"
21 | "fmt"
22 | "io/ioutil"
23 | "math/big"
24 | "os"
25 | "testing"
26 | )
27 |
28 | func TestSm2(t *testing.T) {
29 | priv, err := GenerateKey(rand.Reader) // 生成密钥对
30 | fmt.Println(priv)
31 | if err != nil {
32 | t.Fatal(err)
33 | }
34 | fmt.Printf("%v\n", priv.Curve.IsOnCurve(priv.X, priv.Y)) // 验证是否为sm2的曲线
35 | pub := &priv.PublicKey
36 | msg := []byte("123456")
37 | d0, err := pub.EncryptAsn1(msg, rand.Reader)
38 | if err != nil {
39 | fmt.Printf("Error: failed to encrypt %s: %v\n", msg, err)
40 | return
41 | }
42 | // fmt.Printf("Cipher text = %v\n", d0)
43 | d1, err := priv.DecryptAsn1(d0)
44 | if err != nil {
45 | fmt.Printf("Error: failed to decrypt: %v\n", err)
46 | }
47 | fmt.Printf("clear text = %s\n", d1)
48 | d2, err := Encrypt(pub, msg, rand.Reader, C1C2C3)
49 | if err != nil {
50 | fmt.Printf("Error: failed to encrypt %s: %v\n", msg, err)
51 | return
52 | }
53 | // fmt.Printf("Cipher text = %v\n", d0)
54 | d3, err := Decrypt(priv, d2, C1C2C3)
55 | if err != nil {
56 | fmt.Printf("Error: failed to decrypt: %v\n", err)
57 | }
58 | fmt.Printf("clear text = %s\n", d3)
59 | msg, _ = ioutil.ReadFile("ifile") // 从文件读取数据
60 | sign, err := priv.Sign(rand.Reader, msg, nil) // 签名
61 | if err != nil {
62 | t.Fatal(err)
63 | }
64 |
65 | err = ioutil.WriteFile("TestResult", sign, os.FileMode(0644))
66 | if err != nil {
67 | t.Fatal(err)
68 | }
69 | signdata, _ := ioutil.ReadFile("TestResult")
70 | ok := priv.PublicKey.Verify(msg, signdata) // 密钥验证
71 | if ok != true {
72 | fmt.Printf("Verify error\n")
73 | } else {
74 | fmt.Printf("Verify ok\n")
75 | }
76 | pubKey := priv.PublicKey
77 | ok = pubKey.Verify(msg, signdata) // 公钥验证
78 | if ok != true {
79 | fmt.Printf("Verify error\n")
80 | } else {
81 | fmt.Printf("Verify ok\n")
82 | }
83 |
84 | }
85 |
86 | func BenchmarkSM2(t *testing.B) {
87 | t.ReportAllocs()
88 | msg := []byte("test")
89 | priv, err := GenerateKey(nil) // 生成密钥对
90 | if err != nil {
91 | t.Fatal(err)
92 | }
93 | t.ResetTimer()
94 | for i := 0; i < t.N; i++ {
95 | sign, err := priv.Sign(nil, msg, nil) // 签名
96 | if err != nil {
97 | t.Fatal(err)
98 | }
99 | priv.PublicKey.Verify(msg, sign) // 密钥验证
100 | }
101 | }
102 |
103 | func TestKEB2(t *testing.T) {
104 | ida := []byte{'1', '2', '3', '4', '5', '6', '7', '8',
105 | '1', '2', '3', '4', '5', '6', '7', '8'}
106 | idb := []byte{'1', '2', '3', '4', '5', '6', '7', '8',
107 | '1', '2', '3', '4', '5', '6', '7', '8'}
108 | daBuf := []byte{0x81, 0xEB, 0x26, 0xE9, 0x41, 0xBB, 0x5A, 0xF1,
109 | 0x6D, 0xF1, 0x16, 0x49, 0x5F, 0x90, 0x69, 0x52,
110 | 0x72, 0xAE, 0x2C, 0xD6, 0x3D, 0x6C, 0x4A, 0xE1,
111 | 0x67, 0x84, 0x18, 0xBE, 0x48, 0x23, 0x00, 0x29}
112 | dbBuf := []byte{0x78, 0x51, 0x29, 0x91, 0x7D, 0x45, 0xA9, 0xEA,
113 | 0x54, 0x37, 0xA5, 0x93, 0x56, 0xB8, 0x23, 0x38,
114 | 0xEA, 0xAD, 0xDA, 0x6C, 0xEB, 0x19, 0x90, 0x88,
115 | 0xF1, 0x4A, 0xE1, 0x0D, 0xEF, 0xA2, 0x29, 0xB5}
116 | raBuf := []byte{0xD4, 0xDE, 0x15, 0x47, 0x4D, 0xB7, 0x4D, 0x06,
117 | 0x49, 0x1C, 0x44, 0x0D, 0x30, 0x5E, 0x01, 0x24,
118 | 0x00, 0x99, 0x0F, 0x3E, 0x39, 0x0C, 0x7E, 0x87,
119 | 0x15, 0x3C, 0x12, 0xDB, 0x2E, 0xA6, 0x0B, 0xB3}
120 |
121 | rbBuf := []byte{0x7E, 0x07, 0x12, 0x48, 0x14, 0xB3, 0x09, 0x48,
122 | 0x91, 0x25, 0xEA, 0xED, 0x10, 0x11, 0x13, 0x16,
123 | 0x4E, 0xBF, 0x0F, 0x34, 0x58, 0xC5, 0xBD, 0x88,
124 | 0x33, 0x5C, 0x1F, 0x9D, 0x59, 0x62, 0x43, 0xD6}
125 |
126 | expk := []byte{0x6C, 0x89, 0x34, 0x73, 0x54, 0xDE, 0x24, 0x84,
127 | 0xC6, 0x0B, 0x4A, 0xB1, 0xFD, 0xE4, 0xC6, 0xE5}
128 |
129 | curve := P256Sm2()
130 | curve.ScalarBaseMult(daBuf)
131 | da := new(PrivateKey)
132 | da.PublicKey.Curve = curve
133 | da.D = new(big.Int).SetBytes(daBuf)
134 | da.PublicKey.X, da.PublicKey.Y = curve.ScalarBaseMult(daBuf)
135 |
136 | db := new(PrivateKey)
137 | db.PublicKey.Curve = curve
138 | db.D = new(big.Int).SetBytes(dbBuf)
139 | db.PublicKey.X, db.PublicKey.Y = curve.ScalarBaseMult(dbBuf)
140 |
141 | ra := new(PrivateKey)
142 | ra.PublicKey.Curve = curve
143 | ra.D = new(big.Int).SetBytes(raBuf)
144 | ra.PublicKey.X, ra.PublicKey.Y = curve.ScalarBaseMult(raBuf)
145 |
146 | rb := new(PrivateKey)
147 | rb.PublicKey.Curve = curve
148 | rb.D = new(big.Int).SetBytes(rbBuf)
149 | rb.PublicKey.X, rb.PublicKey.Y = curve.ScalarBaseMult(rbBuf)
150 |
151 | k1, Sb, S2, err := KeyExchangeB(16, ida, idb, db, &da.PublicKey, rb, &ra.PublicKey)
152 | if err != nil {
153 | t.Error(err)
154 | }
155 | k2, S1, Sa, err := KeyExchangeA(16, ida, idb, da, &db.PublicKey, ra, &rb.PublicKey)
156 | if err != nil {
157 | t.Error(err)
158 | }
159 | if bytes.Compare(k1, k2) != 0 {
160 | t.Error("key exchange differ")
161 | }
162 | if bytes.Compare(k1, expk) != 0 {
163 | t.Errorf("expected %x, found %x", expk, k1)
164 | }
165 | if bytes.Compare(S1, Sb) != 0 {
166 | t.Error("hash verfication failed")
167 | }
168 | if bytes.Compare(Sa, S2) != 0 {
169 | t.Error("hash verfication failed")
170 | }
171 | }
172 |
--------------------------------------------------------------------------------
/gmtls/ticket.go:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright Suzhou Tongji Fintech Research Institute 2017 All Rights Reserved.
3 | Licensed under the Apache License, Version 2.0 (the "License");
4 | you may not use this file except in compliance with the License.
5 | You may obtain a copy of the License at
6 |
7 | http://www.apache.org/licenses/LICENSE-2.0
8 |
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
14 | */
15 |
16 | package gmtls
17 |
18 | import (
19 | "bytes"
20 | "crypto/aes"
21 | "crypto/cipher"
22 | "crypto/hmac"
23 | "crypto/sha256"
24 | "crypto/subtle"
25 | "errors"
26 | "io"
27 | )
28 |
29 | // sessionState contains the information that is serialized into a session
30 | // ticket in order to later resume a connection.
31 | type sessionState struct {
32 | vers uint16
33 | cipherSuite uint16
34 | masterSecret []byte
35 | certificates [][]byte
36 | // usedOldKey is true if the ticket from which this session came from
37 | // was encrypted with an older key and thus should be refreshed.
38 | usedOldKey bool
39 | }
40 |
41 | func (s *sessionState) equal(i interface{}) bool {
42 | s1, ok := i.(*sessionState)
43 | if !ok {
44 | return false
45 | }
46 |
47 | if s.vers != s1.vers ||
48 | s.cipherSuite != s1.cipherSuite ||
49 | !bytes.Equal(s.masterSecret, s1.masterSecret) {
50 | return false
51 | }
52 |
53 | if len(s.certificates) != len(s1.certificates) {
54 | return false
55 | }
56 |
57 | for i := range s.certificates {
58 | if !bytes.Equal(s.certificates[i], s1.certificates[i]) {
59 | return false
60 | }
61 | }
62 |
63 | return true
64 | }
65 |
66 | func (s *sessionState) marshal() []byte {
67 | length := 2 + 2 + 2 + len(s.masterSecret) + 2
68 | for _, cert := range s.certificates {
69 | length += 4 + len(cert)
70 | }
71 |
72 | ret := make([]byte, length)
73 | x := ret
74 | x[0] = byte(s.vers >> 8)
75 | x[1] = byte(s.vers)
76 | x[2] = byte(s.cipherSuite >> 8)
77 | x[3] = byte(s.cipherSuite)
78 | x[4] = byte(len(s.masterSecret) >> 8)
79 | x[5] = byte(len(s.masterSecret))
80 | x = x[6:]
81 | copy(x, s.masterSecret)
82 | x = x[len(s.masterSecret):]
83 |
84 | x[0] = byte(len(s.certificates) >> 8)
85 | x[1] = byte(len(s.certificates))
86 | x = x[2:]
87 |
88 | for _, cert := range s.certificates {
89 | x[0] = byte(len(cert) >> 24)
90 | x[1] = byte(len(cert) >> 16)
91 | x[2] = byte(len(cert) >> 8)
92 | x[3] = byte(len(cert))
93 | copy(x[4:], cert)
94 | x = x[4+len(cert):]
95 | }
96 |
97 | return ret
98 | }
99 |
100 | func (s *sessionState) unmarshal(data []byte) bool {
101 | if len(data) < 8 {
102 | return false
103 | }
104 |
105 | s.vers = uint16(data[0])<<8 | uint16(data[1])
106 | s.cipherSuite = uint16(data[2])<<8 | uint16(data[3])
107 | masterSecretLen := int(data[4])<<8 | int(data[5])
108 | data = data[6:]
109 | if len(data) < masterSecretLen {
110 | return false
111 | }
112 |
113 | s.masterSecret = data[:masterSecretLen]
114 | data = data[masterSecretLen:]
115 |
116 | if len(data) < 2 {
117 | return false
118 | }
119 |
120 | numCerts := int(data[0])<<8 | int(data[1])
121 | data = data[2:]
122 |
123 | s.certificates = make([][]byte, numCerts)
124 | for i := range s.certificates {
125 | if len(data) < 4 {
126 | return false
127 | }
128 | certLen := int(data[0])<<24 | int(data[1])<<16 | int(data[2])<<8 | int(data[3])
129 | data = data[4:]
130 | if certLen < 0 {
131 | return false
132 | }
133 | if len(data) < certLen {
134 | return false
135 | }
136 | s.certificates[i] = data[:certLen]
137 | data = data[certLen:]
138 | }
139 |
140 | return len(data) == 0
141 | }
142 |
143 | func (c *Conn) encryptTicket(state *sessionState) ([]byte, error) {
144 | serialized := state.marshal()
145 | encrypted := make([]byte, ticketKeyNameLen+aes.BlockSize+len(serialized)+sha256.Size)
146 | keyName := encrypted[:ticketKeyNameLen]
147 | iv := encrypted[ticketKeyNameLen : ticketKeyNameLen+aes.BlockSize]
148 | macBytes := encrypted[len(encrypted)-sha256.Size:]
149 |
150 | if _, err := io.ReadFull(c.config.rand(), iv); err != nil {
151 | return nil, err
152 | }
153 | key := c.config.ticketKeys()[0]
154 | copy(keyName, key.keyName[:])
155 | block, err := aes.NewCipher(key.aesKey[:])
156 | if err != nil {
157 | return nil, errors.New("tls: failed to create cipher while encrypting ticket: " + err.Error())
158 | }
159 | cipher.NewCTR(block, iv).XORKeyStream(encrypted[ticketKeyNameLen+aes.BlockSize:], serialized)
160 |
161 | mac := hmac.New(sha256.New, key.hmacKey[:])
162 | mac.Write(encrypted[:len(encrypted)-sha256.Size])
163 | mac.Sum(macBytes[:0])
164 |
165 | return encrypted, nil
166 | }
167 |
168 | func (c *Conn) decryptTicket(encrypted []byte) (*sessionState, bool) {
169 | if c.config.SessionTicketsDisabled ||
170 | len(encrypted) < ticketKeyNameLen+aes.BlockSize+sha256.Size {
171 | return nil, false
172 | }
173 |
174 | keyName := encrypted[:ticketKeyNameLen]
175 | iv := encrypted[ticketKeyNameLen : ticketKeyNameLen+aes.BlockSize]
176 | macBytes := encrypted[len(encrypted)-sha256.Size:]
177 |
178 | keys := c.config.ticketKeys()
179 | keyIndex := -1
180 | for i, candidateKey := range keys {
181 | if bytes.Equal(keyName, candidateKey.keyName[:]) {
182 | keyIndex = i
183 | break
184 | }
185 | }
186 |
187 | if keyIndex == -1 {
188 | return nil, false
189 | }
190 | key := &keys[keyIndex]
191 |
192 | mac := hmac.New(sha256.New, key.hmacKey[:])
193 | mac.Write(encrypted[:len(encrypted)-sha256.Size])
194 | expected := mac.Sum(nil)
195 |
196 | if subtle.ConstantTimeCompare(macBytes, expected) != 1 {
197 | return nil, false
198 | }
199 |
200 | block, err := aes.NewCipher(key.aesKey[:])
201 | if err != nil {
202 | return nil, false
203 | }
204 | ciphertext := encrypted[ticketKeyNameLen+aes.BlockSize : len(encrypted)-sha256.Size]
205 | plaintext := ciphertext
206 | cipher.NewCTR(block, iv).XORKeyStream(plaintext, ciphertext)
207 |
208 | state := &sessionState{usedOldKey: keyIndex > 0}
209 | ok := state.unmarshal(plaintext)
210 | return state, ok
211 | }
212 |
--------------------------------------------------------------------------------
/pkcs12/pbkdf.go:
--------------------------------------------------------------------------------
1 | // Copyright 2015 The Go Authors. All rights reserved.
2 | // Use of this source code is governed by a BSD-style
3 | // license that can be found in the LICENSE file.
4 |
5 | package pkcs12
6 |
7 | import (
8 | "bytes"
9 | "crypto/sha1"
10 | "math/big"
11 | )
12 |
13 | var (
14 | one = big.NewInt(1)
15 | )
16 |
17 | // sha1Sum returns the SHA-1 hash of in.
18 | func sha1Sum(in []byte) []byte {
19 | sum := sha1.Sum(in)
20 | return sum[:]
21 | }
22 |
23 | // fillWithRepeats returns v*ceiling(len(pattern) / v) bytes consisting of
24 | // repeats of pattern.
25 | func fillWithRepeats(pattern []byte, v int) []byte {
26 | if len(pattern) == 0 {
27 | return nil
28 | }
29 | outputLen := v * ((len(pattern) + v - 1) / v)
30 | return bytes.Repeat(pattern, (outputLen+len(pattern)-1)/len(pattern))[:outputLen]
31 | }
32 |
33 | func pbkdf(hash func([]byte) []byte, u, v int, salt, password []byte, r int, ID byte, size int) (key []byte) {
34 | // implementation of https://tools.ietf.org/html/rfc7292#appendix-B.2 , RFC text verbatim in comments
35 |
36 | // Let H be a hash function built around a compression function f:
37 |
38 | // Z_2^u x Z_2^v -> Z_2^u
39 |
40 | // (that is, H has a chaining variable and output of length u bits, and
41 | // the message input to the compression function of H is v bits). The
42 | // values for u and v are as follows:
43 |
44 | // HASH FUNCTION VALUE u VALUE v
45 | // MD2, MD5 128 512
46 | // SHA-1 160 512
47 | // SHA-224 224 512
48 | // SHA-256 256 512
49 | // SHA-384 384 1024
50 | // SHA-512 512 1024
51 | // SHA-512/224 224 1024
52 | // SHA-512/256 256 1024
53 |
54 | // Furthermore, let r be the iteration count.
55 |
56 | // We assume here that u and v are both multiples of 8, as are the
57 | // lengths of the password and salt strings (which we denote by p and s,
58 | // respectively) and the number n of pseudorandom bits required. In
59 | // addition, u and v are of course non-zero.
60 |
61 | // For information on security considerations for MD5 [19], see [25] and
62 | // [1], and on those for MD2, see [18].
63 |
64 | // The following procedure can be used to produce pseudorandom bits for
65 | // a particular "purpose" that is identified by a byte called "ID".
66 | // This standard specifies 3 different values for the ID byte:
67 |
68 | // 1. If ID=1, then the pseudorandom bits being produced are to be used
69 | // as key material for performing encryption or decryption.
70 |
71 | // 2. If ID=2, then the pseudorandom bits being produced are to be used
72 | // as an IV (Initial Value) for encryption or decryption.
73 |
74 | // 3. If ID=3, then the pseudorandom bits being produced are to be used
75 | // as an integrity key for MACing.
76 |
77 | // 1. Construct a string, D (the "diversifier"), by concatenating v/8
78 | // copies of ID.
79 | var D []byte
80 | for i := 0; i < v; i++ {
81 | D = append(D, ID)
82 | }
83 |
84 | // 2. Concatenate copies of the salt together to create a string S of
85 | // length v(ceiling(s/v)) bits (the final copy of the salt may be
86 | // truncated to create S). Note that if the salt is the empty
87 | // string, then so is S.
88 |
89 | S := fillWithRepeats(salt, v)
90 |
91 | // 3. Concatenate copies of the password together to create a string P
92 | // of length v(ceiling(p/v)) bits (the final copy of the password
93 | // may be truncated to create P). Note that if the password is the
94 | // empty string, then so is P.
95 |
96 | P := fillWithRepeats(password, v)
97 |
98 | // 4. Set I=S||P to be the concatenation of S and P.
99 | I := append(S, P...)
100 |
101 | // 5. Set c=ceiling(n/u).
102 | c := (size + u - 1) / u
103 |
104 | // 6. For i=1, 2, ..., c, do the following:
105 | A := make([]byte, c*20)
106 | var IjBuf []byte
107 | for i := 0; i < c; i++ {
108 | // A. Set A2=H^r(D||I). (i.e., the r-th hash of D||1,
109 | // H(H(H(... H(D||I))))
110 | Ai := hash(append(D, I...))
111 | for j := 1; j < r; j++ {
112 | Ai = hash(Ai)
113 | }
114 | copy(A[i*20:], Ai[:])
115 |
116 | if i < c-1 { // skip on last iteration
117 | // B. Concatenate copies of Ai to create a string B of length v
118 | // bits (the final copy of Ai may be truncated to create B).
119 | var B []byte
120 | for len(B) < v {
121 | B = append(B, Ai[:]...)
122 | }
123 | B = B[:v]
124 |
125 | // C. Treating I as a concatenation I_0, I_1, ..., I_(k-1) of v-bit
126 | // blocks, where k=ceiling(s/v)+ceiling(p/v), modify I by
127 | // setting I_j=(I_j+B+1) mod 2^v for each j.
128 | {
129 | Bbi := new(big.Int).SetBytes(B)
130 | Ij := new(big.Int)
131 |
132 | for j := 0; j < len(I)/v; j++ {
133 | Ij.SetBytes(I[j*v : (j+1)*v])
134 | Ij.Add(Ij, Bbi)
135 | Ij.Add(Ij, one)
136 | Ijb := Ij.Bytes()
137 | // We expect Ijb to be exactly v bytes,
138 | // if it is longer or shorter we must
139 | // adjust it accordingly.
140 | if len(Ijb) > v {
141 | Ijb = Ijb[len(Ijb)-v:]
142 | }
143 | if len(Ijb) < v {
144 | if IjBuf == nil {
145 | IjBuf = make([]byte, v)
146 | }
147 | bytesShort := v - len(Ijb)
148 | for i := 0; i < bytesShort; i++ {
149 | IjBuf[i] = 0
150 | }
151 | copy(IjBuf[bytesShort:], Ijb)
152 | Ijb = IjBuf
153 | }
154 | copy(I[j*v:(j+1)*v], Ijb)
155 | }
156 | }
157 | }
158 | }
159 | // 7. Concatenate A_1, A_2, ..., A_c together to form a pseudorandom
160 | // bit string, A.
161 |
162 | // 8. Use the first n bits of A as the output of this entire process.
163 | return A[:size]
164 |
165 | // If the above process is being used to generate a DES key, the process
166 | // should be used to create 64 random bits, and the key's parity bits
167 | // should be set after the 64 bits have been produced. Similar concerns
168 | // hold for 2-key and 3-key triple-DES keys, for CDMF keys, and for any
169 | // similar keys with parity bits "built into them".
170 | }
171 |
--------------------------------------------------------------------------------
/gmtls/http_client_test.go:
--------------------------------------------------------------------------------
1 | package gmtls
2 |
3 | import (
4 | "bytes"
5 | "fmt"
6 | "io/ioutil"
7 | "net/http"
8 | "testing"
9 | "time"
10 |
11 | "github.com/tjfoc/gmsm/x509"
12 | )
13 |
14 | var _ExpectRawContent = []byte("Hello World!")
15 |
16 | // 启动HTTP测试服务器
17 | func bootHttpServer(t *testing.T) {
18 | serveMux := http.NewServeMux()
19 | serveMux.HandleFunc("/", func(writer http.ResponseWriter, request *http.Request) {
20 | _, _ = writer.Write(_ExpectRawContent)
21 | })
22 | fmt.Println(">> HTTP :50053 running...")
23 | err := http.ListenAndServe(":50053", serveMux)
24 | if err != nil {
25 | t.Fatal(err)
26 | }
27 | }
28 |
29 | // 启动GM HTTPS测试服务器
30 | func bootGMHTTPSServer(t *testing.T) {
31 | sigCert, err := LoadX509KeyPair(
32 | "websvr/certs/sm2_sign_cert.cer",
33 | "websvr/certs/sm2_sign_key.pem")
34 | if err != nil {
35 | t.Fatal(err)
36 | }
37 | encCert, err := LoadX509KeyPair(
38 | "websvr/certs/sm2_enc_cert.cer",
39 | "websvr/certs/sm2_enc_key.pem")
40 | if err != nil {
41 | t.Fatal(err)
42 | }
43 | config := &Config{
44 | GMSupport: &GMSupport{},
45 | Certificates: []Certificate{sigCert, encCert},
46 | InsecureSkipVerify: true,
47 | }
48 | if err != nil {
49 | panic(err)
50 | }
51 |
52 | ln, err := Listen("tcp", ":50054", config)
53 | if err != nil {
54 | t.Fatal(err)
55 | }
56 | defer ln.Close()
57 | serveMux := http.NewServeMux()
58 | serveMux.HandleFunc("/", func(writer http.ResponseWriter, request *http.Request) {
59 | _, _ = writer.Write(_ExpectRawContent)
60 | })
61 | fmt.Println(">> HTTP :50054 [GMSSL] running...")
62 | err = http.Serve(ln, serveMux)
63 | if err != nil {
64 | t.Fatal(err)
65 | }
66 | }
67 |
68 | // 启动GM HTTPS测试服务器 双向身份认证
69 | func bootGMAuthHTTPSServer(t *testing.T) {
70 | sigCert, err := LoadX509KeyPair(
71 | "websvr/certs/sm2_sign_cert.cer",
72 | "websvr/certs/sm2_sign_key.pem")
73 | if err != nil {
74 | t.Fatal(err)
75 | }
76 | encCert, err := LoadX509KeyPair(
77 | "websvr/certs/sm2_enc_cert.cer",
78 | "websvr/certs/sm2_enc_key.pem")
79 | if err != nil {
80 | t.Fatal(err)
81 | }
82 |
83 | certPool := x509.NewCertPool()
84 | cacert, err := ioutil.ReadFile("websvr/certs/SM2_CA.cer")
85 | if err != nil {
86 | t.Fatal(err)
87 | }
88 | certPool.AppendCertsFromPEM(cacert)
89 |
90 | config := &Config{
91 | GMSupport: &GMSupport{},
92 | Certificates: []Certificate{sigCert, encCert},
93 | ClientAuth: RequireAndVerifyClientCert,
94 | ClientCAs: certPool,
95 | }
96 | if err != nil {
97 | panic(err)
98 | }
99 |
100 | ln, err := Listen("tcp", ":50055", config)
101 | if err != nil {
102 | t.Fatal(err)
103 | }
104 | defer ln.Close()
105 | serveMux := http.NewServeMux()
106 | serveMux.HandleFunc("/", func(writer http.ResponseWriter, request *http.Request) {
107 | _, _ = writer.Write(_ExpectRawContent)
108 | })
109 | fmt.Println(">> HTTP :50055 [GMSSL] Client Auth running...")
110 | err = http.Serve(ln, serveMux)
111 | if err != nil {
112 | t.Fatal(err)
113 | }
114 | }
115 |
116 | // HTTP 客户端连接测试
117 | func TestSimpleNewHTTPSClient1(t *testing.T) {
118 | go bootHttpServer(t)
119 | //go bootGMHTTPSServer(t)
120 | /*
121 | HTTP 连接测试
122 | */
123 | time.Sleep(time.Second)
124 | httpClient := NewCustomHTTPSClient(nil)
125 | response, err := httpClient.Get("http://localhost:50053")
126 | if err != nil {
127 | t.Fatal(err)
128 | }
129 | defer response.Body.Close()
130 | raw, err := ioutil.ReadAll(response.Body)
131 | if err != nil {
132 | t.Fatal(err)
133 | }
134 | if !bytes.Equal(raw, _ExpectRawContent) {
135 | t.Fatalf(">> HTTP响应内容与期待内容不符, expect %s, actual: %s", string(_ExpectRawContent), string(raw))
136 | }
137 | }
138 |
139 | // GM HTTPS 客户端连接测试
140 | func TestNewHTTPSClient2(t *testing.T) {
141 | go bootGMHTTPSServer(t)
142 | /*
143 | GM HTTPS 连接测试
144 | */
145 | time.Sleep(time.Second)
146 | // 信任的根证书
147 |
148 | config, err := createClientGMTLSConfig("", "", []string{"websvr/certs/SM2_CA.cer"})
149 | if err != nil {
150 | t.Fatal(err)
151 | }
152 | httpClient := NewCustomHTTPSClient(config)
153 | response, err := httpClient.Get("https://localhost:50054")
154 | if err != nil {
155 | t.Fatal(err)
156 | }
157 | defer response.Body.Close()
158 | raw, err := ioutil.ReadAll(response.Body)
159 | if err != nil {
160 | t.Fatal(err)
161 | }
162 | if !bytes.Equal(raw, _ExpectRawContent) {
163 | t.Fatalf(">> GM HTTPS响应内容与期待内容不符, expect %s, actual: %s", string(_ExpectRawContent), string(raw))
164 | }
165 | }
166 |
167 | // GM HTTPS 客户端连接测试 双向身份认证
168 | func TestNewHTTPSClient3(t *testing.T) {
169 | go bootGMAuthHTTPSServer(t)
170 | /*
171 | GM HTTPS 双向身份认证
172 | */
173 | time.Sleep(time.Second)
174 |
175 | config, err := createClientGMTLSConfig("websvr/certs/sm2_auth_key.pem", "websvr/certs/sm2_auth_cert.cer", []string{"websvr/certs/SM2_CA.cer"})
176 | if err != nil {
177 | t.Fatal(err)
178 | }
179 | httpClient := NewCustomHTTPSClient(config)
180 |
181 | response, err := httpClient.Get("https://localhost:50055")
182 | if err != nil {
183 | t.Fatal(err)
184 | }
185 | defer response.Body.Close()
186 | raw, err := ioutil.ReadAll(response.Body)
187 | if err != nil {
188 | t.Fatal(err)
189 | }
190 | if !bytes.Equal(raw, _ExpectRawContent) {
191 | t.Fatalf(">> GM HTTPS响应内容与期待内容不符, expect %s, actual: %s", string(_ExpectRawContent), string(raw))
192 | }
193 | }
194 |
195 | func createClientGMTLSConfig(keyPath string, certPath string, caPaths []string) (*Config, error) {
196 |
197 | cfg := &Config{
198 | GMSupport: &GMSupport{},
199 | }
200 | cfg.Certificates = []Certificate{}
201 | if keyPath != "" && certPath != "" {
202 | cert, err := LoadX509KeyPair(certPath, keyPath)
203 | if err != nil {
204 | return nil, fmt.Errorf("load gm X509 keyPair error: %v", err)
205 | }
206 | cfg.Certificates = append(cfg.Certificates, cert)
207 | }
208 |
209 | var pool *x509.CertPool = nil
210 | if len(caPaths) > 0 {
211 | pool = x509.NewCertPool()
212 | for _, certPath := range caPaths {
213 | caCrt, err := ioutil.ReadFile(certPath)
214 | if err != nil {
215 | return nil, err
216 | }
217 | ok := pool.AppendCertsFromPEM(caCrt)
218 | if !ok {
219 | return nil, fmt.Errorf("append cert to pool fail at %s", certPath)
220 | }
221 | }
222 | }
223 |
224 | cfg.MinVersion = VersionGMSSL
225 | cfg.MaxVersion = VersionTLS12
226 |
227 | cfg.PreferServerCipherSuites = true
228 | // cfg.CipherSuites use default value []uint16{GMTLS_SM2_WITH_SM4_SM3, GMTLS_ECDHE_SM2_WITH_SM4_SM3}
229 |
230 | cfg.RootCAs = pool
231 | // cfg.ServerName = "localhost"
232 | cfg.InsecureSkipVerify = false
233 |
234 | return cfg, nil
235 |
236 | }
237 |
--------------------------------------------------------------------------------
/x509/cert_pool.go:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright Suzhou Tongji Fintech Research Institute 2017 All Rights Reserved.
3 | Licensed under the Apache License, Version 2.0 (the "License");
4 | you may not use this file except in compliance with the License.
5 | You may obtain a copy of the License at
6 |
7 | http://www.apache.org/licenses/LICENSE-2.0
8 |
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
14 | */
15 |
16 | package x509
17 |
18 | import (
19 | "encoding/pem"
20 | "errors"
21 | "io/ioutil"
22 | "os"
23 | "runtime"
24 | "sync"
25 | )
26 |
27 | // Possible certificate files; stop after finding one.
28 | var certFiles = []string{
29 | "/etc/ssl/certs/ca-certificates.crt", // Debian/Ubuntu/Gentoo etc.
30 | "/etc/pki/tls/certs/ca-bundle.crt", // Fedora/RHEL 6
31 | "/etc/ssl/ca-bundle.pem", // OpenSUSE
32 | "/etc/pki/tls/cacert.pem", // OpenELEC
33 | "/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem", // CentOS/RHEL 7
34 | }
35 |
36 | // CertPool is a set of certificates.
37 | type CertPool struct {
38 | bySubjectKeyId map[string][]int
39 | byName map[string][]int
40 | certs []*Certificate
41 | }
42 |
43 | // NewCertPool returns a new, empty CertPool.
44 | func NewCertPool() *CertPool {
45 | return &CertPool{
46 | bySubjectKeyId: make(map[string][]int),
47 | byName: make(map[string][]int),
48 | }
49 | }
50 |
51 | // Possible directories with certificate files; stop after successfully
52 | // reading at least one file from a directory.
53 | var certDirectories = []string{
54 | "/etc/ssl/certs", // SLES10/SLES11, https://golang.org/issue/12139
55 | "/system/etc/security/cacerts", // Android
56 | }
57 |
58 | var (
59 | once sync.Once
60 | systemRoots *CertPool
61 | systemRootsErr error
62 | )
63 |
64 | func systemRootsPool() *CertPool {
65 | once.Do(initSystemRoots)
66 | return systemRoots
67 | }
68 |
69 | func initSystemRoots() {
70 | systemRoots, systemRootsErr = loadSystemRoots()
71 | }
72 |
73 | func (c *Certificate) systemVerify(opts *VerifyOptions) (chains [][]*Certificate, err error) {
74 | return nil, nil
75 | }
76 |
77 | func loadSystemRoots() (*CertPool, error) {
78 | roots := NewCertPool()
79 | var firstErr error
80 | for _, file := range certFiles {
81 | data, err := ioutil.ReadFile(file)
82 | if err == nil {
83 | roots.AppendCertsFromPEM(data)
84 | return roots, nil
85 | }
86 | if firstErr == nil && !os.IsNotExist(err) {
87 | firstErr = err
88 | }
89 | }
90 |
91 | for _, directory := range certDirectories {
92 | fis, err := ioutil.ReadDir(directory)
93 | if err != nil {
94 | if firstErr == nil && !os.IsNotExist(err) {
95 | firstErr = err
96 | }
97 | continue
98 | }
99 | rootsAdded := false
100 | for _, fi := range fis {
101 | data, err := ioutil.ReadFile(directory + "/" + fi.Name())
102 | if err == nil && roots.AppendCertsFromPEM(data) {
103 | rootsAdded = true
104 | }
105 | }
106 | if rootsAdded {
107 | return roots, nil
108 | }
109 | }
110 |
111 | return nil, firstErr
112 | }
113 |
114 | // SystemCertPool returns a copy of the system cert pool.
115 | //
116 | // Any mutations to the returned pool are not written to disk and do
117 | // not affect any other pool.
118 | func SystemCertPool() (*CertPool, error) {
119 | if runtime.GOOS == "windows" {
120 | // Issue 16736, 18609:
121 | return nil, errors.New("crypto/x509: system root pool is not available on Windows")
122 | }
123 |
124 | return loadSystemRoots()
125 | }
126 |
127 | // findVerifiedParents attempts to find certificates in s which have signed the
128 | // given certificate. If any candidates were rejected then errCert will be set
129 | // to one of them, arbitrarily, and err will contain the reason that it was
130 | // rejected.
131 | func (s *CertPool) findVerifiedParents(cert *Certificate) (parents []int, errCert *Certificate, err error) {
132 | if s == nil {
133 | return
134 | }
135 | var candidates []int
136 |
137 | if len(cert.AuthorityKeyId) > 0 {
138 | candidates = s.bySubjectKeyId[string(cert.AuthorityKeyId)]
139 | }
140 | if len(candidates) == 0 {
141 | candidates = s.byName[string(cert.RawIssuer)]
142 | }
143 |
144 | for _, c := range candidates {
145 | if err = cert.CheckSignatureFrom(s.certs[c]); err == nil {
146 | parents = append(parents, c)
147 | } else {
148 | errCert = s.certs[c]
149 | }
150 | }
151 |
152 | return
153 | }
154 |
155 | func (s *CertPool) contains(cert *Certificate) bool {
156 | if s == nil {
157 | return false
158 | }
159 |
160 | candidates := s.byName[string(cert.RawSubject)]
161 | for _, c := range candidates {
162 | if s.certs[c].Equal(cert) {
163 | return true
164 | }
165 | }
166 |
167 | return false
168 | }
169 |
170 | // AddCert adds a certificate to a pool.
171 | func (s *CertPool) AddCert(cert *Certificate) {
172 | if cert == nil {
173 | panic("adding nil Certificate to CertPool")
174 | }
175 |
176 | // Check that the certificate isn't being added twice.
177 | if s.contains(cert) {
178 | return
179 | }
180 |
181 | n := len(s.certs)
182 | s.certs = append(s.certs, cert)
183 |
184 | if len(cert.SubjectKeyId) > 0 {
185 | keyId := string(cert.SubjectKeyId)
186 | s.bySubjectKeyId[keyId] = append(s.bySubjectKeyId[keyId], n)
187 | }
188 | name := string(cert.RawSubject)
189 | s.byName[name] = append(s.byName[name], n)
190 | }
191 |
192 | // AppendCertsFromPEM attempts to parse a series of PEM encoded certificates.
193 | // It appends any certificates found to s and reports whether any certificates
194 | // were successfully parsed.
195 | //
196 | // On many Linux systems, /etc/ssl/cert.pem will contain the system wide set
197 | // of root CAs in a format suitable for this function.
198 | func (s *CertPool) AppendCertsFromPEM(pemCerts []byte) (ok bool) {
199 | for len(pemCerts) > 0 {
200 | var block *pem.Block
201 | block, pemCerts = pem.Decode(pemCerts)
202 | if block == nil {
203 | break
204 | }
205 | if block.Type != "CERTIFICATE" || len(block.Headers) != 0 {
206 | continue
207 | }
208 |
209 | cert, err := ParseCertificate(block.Bytes)
210 | if err != nil {
211 | continue
212 | }
213 |
214 | s.AddCert(cert)
215 | ok = true
216 | }
217 |
218 | return
219 | }
220 |
221 | // Subjects returns a list of the DER-encoded subjects of
222 | // all of the certificates in the pool.
223 | func (s *CertPool) Subjects() [][]byte {
224 | res := make([][]byte, len(s.certs))
225 | for i, c := range s.certs {
226 | res[i] = c.RawSubject
227 | }
228 | return res
229 | }
230 |
--------------------------------------------------------------------------------
/x509/ber.go:
--------------------------------------------------------------------------------
1 | package x509
2 |
3 | import (
4 | "bytes"
5 | "errors"
6 | )
7 |
8 | var encodeIndent = 0
9 |
10 | type asn1Object interface {
11 | EncodeTo(writer *bytes.Buffer) error
12 | }
13 |
14 | type asn1Structured struct {
15 | tagBytes []byte
16 | content []asn1Object
17 | }
18 |
19 | func (s asn1Structured) EncodeTo(out *bytes.Buffer) error {
20 | //fmt.Printf("%s--> tag: % X\n", strings.Repeat("| ", encodeIndent), s.tagBytes)
21 | encodeIndent++
22 | inner := new(bytes.Buffer)
23 | for _, obj := range s.content {
24 | err := obj.EncodeTo(inner)
25 | if err != nil {
26 | return err
27 | }
28 | }
29 | encodeIndent--
30 | out.Write(s.tagBytes)
31 | encodeLength(out, inner.Len())
32 | out.Write(inner.Bytes())
33 | return nil
34 | }
35 |
36 | type asn1Primitive struct {
37 | tagBytes []byte
38 | length int
39 | content []byte
40 | }
41 |
42 | func (p asn1Primitive) EncodeTo(out *bytes.Buffer) error {
43 | _, err := out.Write(p.tagBytes)
44 | if err != nil {
45 | return err
46 | }
47 | if err = encodeLength(out, p.length); err != nil {
48 | return err
49 | }
50 | //fmt.Printf("%s--> tag: % X length: %d\n", strings.Repeat("| ", encodeIndent), p.tagBytes, p.length)
51 | //fmt.Printf("%s--> content length: %d\n", strings.Repeat("| ", encodeIndent), len(p.content))
52 | out.Write(p.content)
53 |
54 | return nil
55 | }
56 |
57 | func ber2der(ber []byte) ([]byte, error) {
58 | if len(ber) == 0 {
59 | return nil, errors.New("ber2der: input ber is empty")
60 | }
61 | //fmt.Printf("--> ber2der: Transcoding %d bytes\n", len(ber))
62 | out := new(bytes.Buffer)
63 |
64 | obj, _, err := readObject(ber, 0)
65 | if err != nil {
66 | return nil, err
67 | }
68 | obj.EncodeTo(out)
69 |
70 | // if offset < len(ber) {
71 | // return nil, fmt.Errorf("ber2der: Content longer than expected. Got %d, expected %d", offset, len(ber))
72 | //}
73 |
74 | return out.Bytes(), nil
75 | }
76 |
77 | // encodes lengths that are longer than 127 into string of bytes
78 | func marshalLongLength(out *bytes.Buffer, i int) (err error) {
79 | n := lengthLength(i)
80 |
81 | for ; n > 0; n-- {
82 | err = out.WriteByte(byte(i >> uint((n-1)*8)))
83 | if err != nil {
84 | return
85 | }
86 | }
87 |
88 | return nil
89 | }
90 |
91 | // computes the byte length of an encoded length value
92 | func lengthLength(i int) (numBytes int) {
93 | numBytes = 1
94 | for i > 255 {
95 | numBytes++
96 | i >>= 8
97 | }
98 | return
99 | }
100 |
101 | // encodes the length in DER format
102 | // If the length fits in 7 bits, the value is encoded directly.
103 | //
104 | // Otherwise, the number of bytes to encode the length is first determined.
105 | // This number is likely to be 4 or less for a 32bit length. This number is
106 | // added to 0x80. The length is encoded in big endian encoding follow after
107 | //
108 | // Examples:
109 | // length | byte 1 | bytes n
110 | // 0 | 0x00 | -
111 | // 120 | 0x78 | -
112 | // 200 | 0x81 | 0xC8
113 | // 500 | 0x82 | 0x01 0xF4
114 | //
115 | func encodeLength(out *bytes.Buffer, length int) (err error) {
116 | if length >= 128 {
117 | l := lengthLength(length)
118 | err = out.WriteByte(0x80 | byte(l))
119 | if err != nil {
120 | return
121 | }
122 | err = marshalLongLength(out, length)
123 | if err != nil {
124 | return
125 | }
126 | } else {
127 | err = out.WriteByte(byte(length))
128 | if err != nil {
129 | return
130 | }
131 | }
132 | return
133 | }
134 |
135 | func readObject(ber []byte, offset int) (asn1Object, int, error) {
136 | //fmt.Printf("\n====> Starting readObject at offset: %d\n\n", offset)
137 | tagStart := offset
138 | b := ber[offset]
139 | offset++
140 | tag := b & 0x1F // last 5 bits
141 | if tag == 0x1F {
142 | tag = 0
143 | for ber[offset] >= 0x80 {
144 | tag = tag*128 + ber[offset] - 0x80
145 | offset++
146 | }
147 | tag = tag*128 + ber[offset] - 0x80
148 | offset++
149 | }
150 | tagEnd := offset
151 |
152 | kind := b & 0x20
153 | /*
154 | if kind == 0 {
155 | fmt.Print("--> Primitive\n")
156 | } else {
157 | fmt.Print("--> Constructed\n")
158 | }
159 | */
160 | // read length
161 | var length int
162 | l := ber[offset]
163 | offset++
164 | indefinite := false
165 | if l > 0x80 {
166 | numberOfBytes := (int)(l & 0x7F)
167 | if numberOfBytes > 4 { // int is only guaranteed to be 32bit
168 | return nil, 0, errors.New("ber2der: BER tag length too long")
169 | }
170 | if numberOfBytes == 4 && (int)(ber[offset]) > 0x7F {
171 | return nil, 0, errors.New("ber2der: BER tag length is negative")
172 | }
173 | if 0x0 == (int)(ber[offset]) {
174 | return nil, 0, errors.New("ber2der: BER tag length has leading zero")
175 | }
176 | //fmt.Printf("--> (compute length) indicator byte: %x\n", l)
177 | //fmt.Printf("--> (compute length) length bytes: % X\n", ber[offset:offset+numberOfBytes])
178 | for i := 0; i < numberOfBytes; i++ {
179 | length = length*256 + (int)(ber[offset])
180 | offset++
181 | }
182 | } else if l == 0x80 {
183 | indefinite = true
184 | } else {
185 | length = (int)(l)
186 | }
187 |
188 | //fmt.Printf("--> length : %d\n", length)
189 | contentEnd := offset + length
190 | if contentEnd > len(ber) {
191 | return nil, 0, errors.New("ber2der: BER tag length is more than available data")
192 | }
193 | //fmt.Printf("--> content start : %d\n", offset)
194 | //fmt.Printf("--> content end : %d\n", contentEnd)
195 | //fmt.Printf("--> content : % X\n", ber[offset:contentEnd])
196 | var obj asn1Object
197 | if indefinite && kind == 0 {
198 | return nil, 0, errors.New("ber2der: Indefinite form tag must have constructed encoding")
199 | }
200 | if kind == 0 {
201 | obj = asn1Primitive{
202 | tagBytes: ber[tagStart:tagEnd],
203 | length: length,
204 | content: ber[offset:contentEnd],
205 | }
206 | } else {
207 | var subObjects []asn1Object
208 | for (offset < contentEnd) || indefinite {
209 | var subObj asn1Object
210 | var err error
211 | subObj, offset, err = readObject(ber, offset)
212 | if err != nil {
213 | return nil, 0, err
214 | }
215 | subObjects = append(subObjects, subObj)
216 |
217 | if indefinite {
218 | terminated, err := isIndefiniteTermination(ber, offset)
219 | if err != nil {
220 | return nil, 0, err
221 | }
222 |
223 | if terminated {
224 | break
225 | }
226 | }
227 | }
228 | obj = asn1Structured{
229 | tagBytes: ber[tagStart:tagEnd],
230 | content: subObjects,
231 | }
232 | }
233 |
234 | // Apply indefinite form length with 0x0000 terminator.
235 | if indefinite {
236 | contentEnd = offset + 2
237 | }
238 |
239 | return obj, contentEnd, nil
240 | }
241 |
242 | func isIndefiniteTermination(ber []byte, offset int) (bool, error) {
243 | if len(ber)-offset < 2 {
244 | return false, errors.New("ber2der: Invalid BER format")
245 | }
246 |
247 | return bytes.Index(ber[offset:], []byte{0x0, 0x0}) == 0, nil
248 | }
249 |
--------------------------------------------------------------------------------
/gmtls/gmcredentials/credentials.go:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright Suzhou Tongji Fintech Research Institute 2017 All Rights Reserved.
3 | Licensed under the Apache License, Version 2.0 (the "License");
4 | you may not use this file except in compliance with the License.
5 | You may obtain a copy of the License at
6 |
7 | http://www.apache.org/licenses/LICENSE-2.0
8 |
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
14 | */
15 |
16 | package gmcredentials
17 |
18 | import (
19 | "errors"
20 | "fmt"
21 | "io/ioutil"
22 | "net"
23 | "strings"
24 |
25 | "github.com/tjfoc/gmsm/gmtls"
26 | "github.com/tjfoc/gmsm/x509"
27 | "golang.org/x/net/context"
28 | "google.golang.org/grpc/credentials"
29 | )
30 |
31 | var (
32 | // alpnProtoStr are the specified application level protocols for gRPC.
33 | alpnProtoStr = []string{"h2"}
34 | )
35 |
36 | // PerRPCCredentials defines the common interface for the credentials which need to
37 | // attach security information to every RPC (e.g., oauth2).
38 | type PerRPCCredentials interface {
39 | // GetRequestMetadata gets the current request metadata, refreshing
40 | // tokens if required. This should be called by the transport layer on
41 | // each request, and the data should be populated in headers or other
42 | // context. uri is the URI of the entry point for the request. When
43 | // supported by the underlying implementation, ctx can be used for
44 | // timeout and cancellation.
45 | // TODO(zhaoq): Define the set of the qualified keys instead of leaving
46 | // it as an arbitrary string.
47 | GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error)
48 | // RequireTransportSecurity indicates whether the credentials requires
49 | // transport security.
50 | RequireTransportSecurity() bool
51 | }
52 |
53 | // ProtocolInfo provides information regarding the gRPC wire protocol version,
54 | // security protocol, security protocol version in use, server name, etc.
55 | type ProtocolInfo struct {
56 | // ProtocolVersion is the gRPC wire protocol version.
57 | ProtocolVersion string
58 | // SecurityProtocol is the security protocol in use.
59 | SecurityProtocol string
60 | // SecurityVersion is the security protocol version.
61 | SecurityVersion string
62 | // ServerName is the user-configured server name.
63 | ServerName string
64 | }
65 |
66 | // AuthInfo defines the common interface for the auth information the users are interested in.
67 | type AuthInfo interface {
68 | AuthType() string
69 | }
70 |
71 | var (
72 | // ErrConnDispatched indicates that rawConn has been dispatched out of gRPC
73 | // and the caller should not close rawConn.
74 | ErrConnDispatched = errors.New("credentials: rawConn is dispatched out of gRPC")
75 | )
76 |
77 | // TLSInfo contains the auth information for a TLS authenticated connection.
78 | // It implements the AuthInfo interface.
79 | type TLSInfo struct {
80 | State gmtls.ConnectionState
81 | }
82 |
83 | // AuthType returns the type of TLSInfo as a string.
84 | func (t TLSInfo) AuthType() string {
85 | return "tls"
86 | }
87 |
88 | // tlsCreds is the credentials required for authenticating a connection using TLS.
89 | type tlsCreds struct {
90 | // TLS configuration
91 | config *gmtls.Config
92 | }
93 |
94 | func (c tlsCreds) Info() credentials.ProtocolInfo {
95 | return credentials.ProtocolInfo{
96 | SecurityProtocol: "tls",
97 | SecurityVersion: "1.2",
98 | ServerName: c.config.ServerName,
99 | }
100 | }
101 |
102 | func (c *tlsCreds) ClientHandshake(ctx context.Context, addr string, rawConn net.Conn) (_ net.Conn, _ credentials.AuthInfo, err error) {
103 | // use local cfg to avoid clobbering ServerName if using multiple endpoints
104 | cfg := cloneTLSConfig(c.config)
105 | if cfg.ServerName == "" {
106 | colonPos := strings.LastIndex(addr, ":")
107 | if colonPos == -1 {
108 | colonPos = len(addr)
109 | }
110 | cfg.ServerName = addr[:colonPos]
111 | }
112 | conn := gmtls.Client(rawConn, cfg)
113 | errChannel := make(chan error, 1)
114 | go func() {
115 | errChannel <- conn.Handshake()
116 | }()
117 | select {
118 | case err := <-errChannel:
119 | if err != nil {
120 | return nil, nil, err
121 | }
122 | case <-ctx.Done():
123 | return nil, nil, ctx.Err()
124 | }
125 | return conn, TLSInfo{conn.ConnectionState()}, nil
126 | }
127 |
128 | func (c *tlsCreds) ServerHandshake(rawConn net.Conn) (net.Conn, credentials.AuthInfo, error) {
129 | conn := gmtls.Server(rawConn, c.config)
130 | if err := conn.Handshake(); err != nil {
131 | return nil, nil, err
132 | }
133 | return conn, TLSInfo{conn.ConnectionState()}, nil
134 | }
135 |
136 | func (c *tlsCreds) Clone() credentials.TransportCredentials {
137 | return NewTLS(c.config)
138 | }
139 |
140 | func (c *tlsCreds) OverrideServerName(serverNameOverride string) error {
141 | c.config.ServerName = serverNameOverride
142 | return nil
143 | }
144 |
145 | // NewTLS uses c to construct a TransportCredentials based on TLS.
146 | func NewTLS(c *gmtls.Config) credentials.TransportCredentials {
147 | tc := &tlsCreds{cloneTLSConfig(c)}
148 | tc.config.NextProtos = alpnProtoStr
149 | return tc
150 | }
151 |
152 | // NewClientTLSFromCert constructs TLS credentials from the input certificate for client.
153 | // serverNameOverride is for testing only. If set to a non empty string,
154 | // it will override the virtual host name of authority (e.g. :authority header field) in requests.
155 | func NewClientTLSFromCert(cp *x509.CertPool, serverNameOverride string) credentials.TransportCredentials {
156 | return NewTLS(&gmtls.Config{GMSupport: &gmtls.GMSupport{}, ServerName: serverNameOverride, RootCAs: cp})
157 | }
158 |
159 | // NewClientTLSFromFile constructs TLS credentials from the input certificate file for client.
160 | // serverNameOverride is for testing only. If set to a non empty string,
161 | // it will override the virtual host name of authority (e.g. :authority header field) in requests.
162 | func NewClientTLSFromFile(certFile, serverNameOverride string) (credentials.TransportCredentials, error) {
163 | b, err := ioutil.ReadFile(certFile)
164 | if err != nil {
165 | return nil, err
166 | }
167 | cp := x509.NewCertPool()
168 | if !cp.AppendCertsFromPEM(b) {
169 | return nil, fmt.Errorf("credentials: failed to append certificates")
170 | }
171 | return NewTLS(&gmtls.Config{ServerName: serverNameOverride, RootCAs: cp}), nil
172 | }
173 |
174 | // NewServerTLSFromCert constructs TLS credentials from the input certificate for server.
175 | func NewServerTLSFromCert(cert *gmtls.Certificate) credentials.TransportCredentials {
176 | return NewTLS(&gmtls.Config{Certificates: []gmtls.Certificate{*cert}})
177 | }
178 |
179 | // NewServerTLSFromFile constructs TLS credentials from the input certificate file and key
180 | // file for server.
181 | func NewServerTLSFromFile(certFile, keyFile string) (credentials.TransportCredentials, error) {
182 | cert, err := gmtls.LoadX509KeyPair(certFile, keyFile)
183 | if err != nil {
184 | return nil, err
185 | }
186 | return NewTLS(&gmtls.Config{Certificates: []gmtls.Certificate{cert}}), nil
187 | }
188 |
--------------------------------------------------------------------------------
/pkcs12/rc2.go:
--------------------------------------------------------------------------------
1 | // Copyright 2015 The Go Authors. All rights reserved.
2 | // Use of this source code is governed by a BSD-style
3 | // license that can be found in the LICENSE file.
4 |
5 | // Package rc2 implements the RC2 cipher
6 | /*
7 | https://www.ietf.org/rfc/rfc2268.txt
8 | http://people.csail.mit.edu/rivest/pubs/KRRR98.pdf
9 |
10 | This code is licensed under the MIT license.
11 | */
12 | package pkcs12
13 |
14 | import (
15 | "crypto/cipher"
16 | "encoding/binary"
17 | )
18 |
19 | // The rc2 block size in bytes
20 | const BlockSize = 8
21 |
22 | type rc2Cipher struct {
23 | k [64]uint16
24 | }
25 |
26 | // New returns a new rc2 cipher with the given key and effective key length t1
27 | func New(key []byte, t1 int) (cipher.Block, error) {
28 | // TODO(dgryski): error checking for key length
29 | return &rc2Cipher{
30 | k: expandKey(key, t1),
31 | }, nil
32 | }
33 |
34 | func (*rc2Cipher) BlockSize() int { return BlockSize }
35 |
36 | var piTable = [256]byte{
37 | 0xd9, 0x78, 0xf9, 0xc4, 0x19, 0xdd, 0xb5, 0xed, 0x28, 0xe9, 0xfd, 0x79, 0x4a, 0xa0, 0xd8, 0x9d,
38 | 0xc6, 0x7e, 0x37, 0x83, 0x2b, 0x76, 0x53, 0x8e, 0x62, 0x4c, 0x64, 0x88, 0x44, 0x8b, 0xfb, 0xa2,
39 | 0x17, 0x9a, 0x59, 0xf5, 0x87, 0xb3, 0x4f, 0x13, 0x61, 0x45, 0x6d, 0x8d, 0x09, 0x81, 0x7d, 0x32,
40 | 0xbd, 0x8f, 0x40, 0xeb, 0x86, 0xb7, 0x7b, 0x0b, 0xf0, 0x95, 0x21, 0x22, 0x5c, 0x6b, 0x4e, 0x82,
41 | 0x54, 0xd6, 0x65, 0x93, 0xce, 0x60, 0xb2, 0x1c, 0x73, 0x56, 0xc0, 0x14, 0xa7, 0x8c, 0xf1, 0xdc,
42 | 0x12, 0x75, 0xca, 0x1f, 0x3b, 0xbe, 0xe4, 0xd1, 0x42, 0x3d, 0xd4, 0x30, 0xa3, 0x3c, 0xb6, 0x26,
43 | 0x6f, 0xbf, 0x0e, 0xda, 0x46, 0x69, 0x07, 0x57, 0x27, 0xf2, 0x1d, 0x9b, 0xbc, 0x94, 0x43, 0x03,
44 | 0xf8, 0x11, 0xc7, 0xf6, 0x90, 0xef, 0x3e, 0xe7, 0x06, 0xc3, 0xd5, 0x2f, 0xc8, 0x66, 0x1e, 0xd7,
45 | 0x08, 0xe8, 0xea, 0xde, 0x80, 0x52, 0xee, 0xf7, 0x84, 0xaa, 0x72, 0xac, 0x35, 0x4d, 0x6a, 0x2a,
46 | 0x96, 0x1a, 0xd2, 0x71, 0x5a, 0x15, 0x49, 0x74, 0x4b, 0x9f, 0xd0, 0x5e, 0x04, 0x18, 0xa4, 0xec,
47 | 0xc2, 0xe0, 0x41, 0x6e, 0x0f, 0x51, 0xcb, 0xcc, 0x24, 0x91, 0xaf, 0x50, 0xa1, 0xf4, 0x70, 0x39,
48 | 0x99, 0x7c, 0x3a, 0x85, 0x23, 0xb8, 0xb4, 0x7a, 0xfc, 0x02, 0x36, 0x5b, 0x25, 0x55, 0x97, 0x31,
49 | 0x2d, 0x5d, 0xfa, 0x98, 0xe3, 0x8a, 0x92, 0xae, 0x05, 0xdf, 0x29, 0x10, 0x67, 0x6c, 0xba, 0xc9,
50 | 0xd3, 0x00, 0xe6, 0xcf, 0xe1, 0x9e, 0xa8, 0x2c, 0x63, 0x16, 0x01, 0x3f, 0x58, 0xe2, 0x89, 0xa9,
51 | 0x0d, 0x38, 0x34, 0x1b, 0xab, 0x33, 0xff, 0xb0, 0xbb, 0x48, 0x0c, 0x5f, 0xb9, 0xb1, 0xcd, 0x2e,
52 | 0xc5, 0xf3, 0xdb, 0x47, 0xe5, 0xa5, 0x9c, 0x77, 0x0a, 0xa6, 0x20, 0x68, 0xfe, 0x7f, 0xc1, 0xad,
53 | }
54 |
55 | func expandKey(key []byte, t1 int) [64]uint16 {
56 |
57 | l := make([]byte, 128)
58 | copy(l, key)
59 |
60 | var t = len(key)
61 | var t8 = (t1 + 7) / 8
62 | var tm = byte(255 % uint(1<<(8+uint(t1)-8*uint(t8))))
63 |
64 | for i := len(key); i < 128; i++ {
65 | l[i] = piTable[l[i-1]+l[uint8(i-t)]]
66 | }
67 |
68 | l[128-t8] = piTable[l[128-t8]&tm]
69 |
70 | for i := 127 - t8; i >= 0; i-- {
71 | l[i] = piTable[l[i+1]^l[i+t8]]
72 | }
73 |
74 | var k [64]uint16
75 |
76 | for i := range k {
77 | k[i] = uint16(l[2*i]) + uint16(l[2*i+1])*256
78 | }
79 |
80 | return k
81 | }
82 |
83 | func rotl16(x uint16, b uint) uint16 {
84 | return (x >> (16 - b)) | (x << b)
85 | }
86 |
87 | func (c *rc2Cipher) Encrypt(dst, src []byte) {
88 |
89 | r0 := binary.LittleEndian.Uint16(src[0:])
90 | r1 := binary.LittleEndian.Uint16(src[2:])
91 | r2 := binary.LittleEndian.Uint16(src[4:])
92 | r3 := binary.LittleEndian.Uint16(src[6:])
93 |
94 | var j int
95 |
96 | for j <= 16 {
97 | // mix r0
98 | r0 = r0 + c.k[j] + (r3 & r2) + ((^r3) & r1)
99 | r0 = rotl16(r0, 1)
100 | j++
101 |
102 | // mix r1
103 | r1 = r1 + c.k[j] + (r0 & r3) + ((^r0) & r2)
104 | r1 = rotl16(r1, 2)
105 | j++
106 |
107 | // mix r2
108 | r2 = r2 + c.k[j] + (r1 & r0) + ((^r1) & r3)
109 | r2 = rotl16(r2, 3)
110 | j++
111 |
112 | // mix r3
113 | r3 = r3 + c.k[j] + (r2 & r1) + ((^r2) & r0)
114 | r3 = rotl16(r3, 5)
115 | j++
116 |
117 | }
118 |
119 | r0 = r0 + c.k[r3&63]
120 | r1 = r1 + c.k[r0&63]
121 | r2 = r2 + c.k[r1&63]
122 | r3 = r3 + c.k[r2&63]
123 |
124 | for j <= 40 {
125 |
126 | // mix r0
127 | r0 = r0 + c.k[j] + (r3 & r2) + ((^r3) & r1)
128 | r0 = rotl16(r0, 1)
129 | j++
130 |
131 | // mix r1
132 | r1 = r1 + c.k[j] + (r0 & r3) + ((^r0) & r2)
133 | r1 = rotl16(r1, 2)
134 | j++
135 |
136 | // mix r2
137 | r2 = r2 + c.k[j] + (r1 & r0) + ((^r1) & r3)
138 | r2 = rotl16(r2, 3)
139 | j++
140 |
141 | // mix r3
142 | r3 = r3 + c.k[j] + (r2 & r1) + ((^r2) & r0)
143 | r3 = rotl16(r3, 5)
144 | j++
145 |
146 | }
147 |
148 | r0 = r0 + c.k[r3&63]
149 | r1 = r1 + c.k[r0&63]
150 | r2 = r2 + c.k[r1&63]
151 | r3 = r3 + c.k[r2&63]
152 |
153 | for j <= 60 {
154 |
155 | // mix r0
156 | r0 = r0 + c.k[j] + (r3 & r2) + ((^r3) & r1)
157 | r0 = rotl16(r0, 1)
158 | j++
159 |
160 | // mix r1
161 | r1 = r1 + c.k[j] + (r0 & r3) + ((^r0) & r2)
162 | r1 = rotl16(r1, 2)
163 | j++
164 |
165 | // mix r2
166 | r2 = r2 + c.k[j] + (r1 & r0) + ((^r1) & r3)
167 | r2 = rotl16(r2, 3)
168 | j++
169 |
170 | // mix r3
171 | r3 = r3 + c.k[j] + (r2 & r1) + ((^r2) & r0)
172 | r3 = rotl16(r3, 5)
173 | j++
174 | }
175 |
176 | binary.LittleEndian.PutUint16(dst[0:], r0)
177 | binary.LittleEndian.PutUint16(dst[2:], r1)
178 | binary.LittleEndian.PutUint16(dst[4:], r2)
179 | binary.LittleEndian.PutUint16(dst[6:], r3)
180 | }
181 |
182 | func (c *rc2Cipher) Decrypt(dst, src []byte) {
183 |
184 | r0 := binary.LittleEndian.Uint16(src[0:])
185 | r1 := binary.LittleEndian.Uint16(src[2:])
186 | r2 := binary.LittleEndian.Uint16(src[4:])
187 | r3 := binary.LittleEndian.Uint16(src[6:])
188 |
189 | j := 63
190 |
191 | for j >= 44 {
192 | // unmix r3
193 | r3 = rotl16(r3, 16-5)
194 | r3 = r3 - c.k[j] - (r2 & r1) - ((^r2) & r0)
195 | j--
196 |
197 | // unmix r2
198 | r2 = rotl16(r2, 16-3)
199 | r2 = r2 - c.k[j] - (r1 & r0) - ((^r1) & r3)
200 | j--
201 |
202 | // unmix r1
203 | r1 = rotl16(r1, 16-2)
204 | r1 = r1 - c.k[j] - (r0 & r3) - ((^r0) & r2)
205 | j--
206 |
207 | // unmix r0
208 | r0 = rotl16(r0, 16-1)
209 | r0 = r0 - c.k[j] - (r3 & r2) - ((^r3) & r1)
210 | j--
211 | }
212 |
213 | r3 = r3 - c.k[r2&63]
214 | r2 = r2 - c.k[r1&63]
215 | r1 = r1 - c.k[r0&63]
216 | r0 = r0 - c.k[r3&63]
217 |
218 | for j >= 20 {
219 | // unmix r3
220 | r3 = rotl16(r3, 16-5)
221 | r3 = r3 - c.k[j] - (r2 & r1) - ((^r2) & r0)
222 | j--
223 |
224 | // unmix r2
225 | r2 = rotl16(r2, 16-3)
226 | r2 = r2 - c.k[j] - (r1 & r0) - ((^r1) & r3)
227 | j--
228 |
229 | // unmix r1
230 | r1 = rotl16(r1, 16-2)
231 | r1 = r1 - c.k[j] - (r0 & r3) - ((^r0) & r2)
232 | j--
233 |
234 | // unmix r0
235 | r0 = rotl16(r0, 16-1)
236 | r0 = r0 - c.k[j] - (r3 & r2) - ((^r3) & r1)
237 | j--
238 |
239 | }
240 |
241 | r3 = r3 - c.k[r2&63]
242 | r2 = r2 - c.k[r1&63]
243 | r1 = r1 - c.k[r0&63]
244 | r0 = r0 - c.k[r3&63]
245 |
246 | for j >= 0 {
247 |
248 | // unmix r3
249 | r3 = rotl16(r3, 16-5)
250 | r3 = r3 - c.k[j] - (r2 & r1) - ((^r2) & r0)
251 | j--
252 |
253 | // unmix r2
254 | r2 = rotl16(r2, 16-3)
255 | r2 = r2 - c.k[j] - (r1 & r0) - ((^r1) & r3)
256 | j--
257 |
258 | // unmix r1
259 | r1 = rotl16(r1, 16-2)
260 | r1 = r1 - c.k[j] - (r0 & r3) - ((^r0) & r2)
261 | j--
262 |
263 | // unmix r0
264 | r0 = rotl16(r0, 16-1)
265 | r0 = r0 - c.k[j] - (r3 & r2) - ((^r3) & r1)
266 | j--
267 |
268 | }
269 |
270 | binary.LittleEndian.PutUint16(dst[0:], r0)
271 | binary.LittleEndian.PutUint16(dst[2:], r1)
272 | binary.LittleEndian.PutUint16(dst[4:], r2)
273 | binary.LittleEndian.PutUint16(dst[6:], r3)
274 | }
275 |
--------------------------------------------------------------------------------
/pkcs12/pkcs8.go:
--------------------------------------------------------------------------------
1 | // Copyright 2015 The Go Authors. All rights reserved.
2 | // Use of this source code is governed by a BSD-style
3 | // license that can be found in the LICENSE file.
4 |
5 | package pkcs12
6 |
7 | import (
8 | "crypto/ecdsa"
9 | "crypto/elliptic"
10 | "crypto/rsa"
11 | "crypto/x509"
12 | "crypto/x509/pkix"
13 | "encoding/asn1"
14 | "errors"
15 | "github.com/tjfoc/gmsm/sm2"
16 | "fmt"
17 | "math/big"
18 | )
19 |
20 | type pkcs8 struct { // Duplicated from x509 package
21 | Version int
22 | Algo pkix.AlgorithmIdentifier
23 | PrivateKey []byte
24 | }
25 |
26 | var ( // Duplicated from x509 package
27 | oidPublicKeyRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 1}
28 | oidPublicKeyECDSA = asn1.ObjectIdentifier{1, 2, 840, 10045, 2, 1}
29 | )
30 |
31 | var ( // Duplicated from x509 package
32 | oidNamedCurveP224 = asn1.ObjectIdentifier{1, 3, 132, 0, 33}
33 | oidNamedCurveP256 = asn1.ObjectIdentifier{1, 2, 840, 10045, 3, 1, 7}
34 | oidNamedCurveP384 = asn1.ObjectIdentifier{1, 3, 132, 0, 34}
35 | oidNamedCurveP521 = asn1.ObjectIdentifier{1, 3, 132, 0, 35}
36 | oidNamedCurveP256SM2 = asn1.ObjectIdentifier{1, 2, 156, 10197, 1, 301} // I get the SM2 ID through parsing the pem file generated by gmssl
37 | )
38 |
39 | func oidFromNamedCurve(curve elliptic.Curve) (asn1.ObjectIdentifier, bool) { // Duplicated from x509 package
40 | switch curve {
41 | case elliptic.P224():
42 | return oidNamedCurveP224, true
43 | case elliptic.P256():
44 | return oidNamedCurveP256, true
45 | case elliptic.P384():
46 | return oidNamedCurveP384, true
47 | case elliptic.P521():
48 | return oidNamedCurveP521, true
49 | case sm2.P256Sm2():
50 | return oidNamedCurveP256SM2, true
51 | }
52 |
53 | return nil, false
54 | }
55 | func namedCurveFromOID(oid asn1.ObjectIdentifier) elliptic.Curve {
56 | switch {
57 | case oid.Equal(oidNamedCurveP224):
58 | return elliptic.P224()
59 | case oid.Equal(oidNamedCurveP256):
60 | return elliptic.P256()
61 | case oid.Equal(oidNamedCurveP384):
62 | return elliptic.P384()
63 | case oid.Equal(oidNamedCurveP521):
64 | return elliptic.P521()
65 | case oid.Equal(oidNamedCurveP256SM2):
66 | return sm2.P256Sm2()
67 | }
68 | return nil
69 | }
70 | func ParsePKCS8PrivateKey(der []byte) (key interface{}, err error) {
71 | var privKey pkcs8
72 | if _, err := asn1.Unmarshal(der, &privKey); err != nil {
73 | return nil, err
74 | }
75 | switch {
76 | case privKey.Algo.Algorithm.Equal(oidPublicKeyECDSA):
77 | bytes := privKey.Algo.Parameters.FullBytes
78 | namedCurveOID := new(asn1.ObjectIdentifier)
79 | if _, err := asn1.Unmarshal(bytes, namedCurveOID); err != nil {
80 | namedCurveOID = nil
81 | }
82 | key, err = parseECPrivateKey(namedCurveOID, privKey.PrivateKey)
83 | if err != nil {
84 | return nil, errors.New("x509: failed to parse EC private key embedded in PKCS#8: " + err.Error())
85 | }
86 | return key, nil
87 |
88 | default:
89 | return nil, fmt.Errorf("x509: PKCS#8 wrapping contained private key with unknown algorithm: %v", privKey.Algo.Algorithm)
90 | }
91 | }
92 | func parseECPrivateKey(namedCurveOID *asn1.ObjectIdentifier, der []byte) (key *ecdsa.PrivateKey, err error) {
93 | var privKey ecPrivateKey
94 | if _, err := asn1.Unmarshal(der, &privKey); err != nil {
95 | return nil, errors.New("x509: failed to parse EC private key: " + err.Error())
96 | }
97 | if privKey.Version != 1 {
98 | return nil, fmt.Errorf("x509: unknown EC private key version %d", privKey.Version)
99 | }
100 |
101 | var curve elliptic.Curve
102 | if namedCurveOID != nil {
103 | curve = namedCurveFromOID(*namedCurveOID)
104 | } else {
105 | curve = namedCurveFromOID(privKey.NamedCurveOID)
106 | }
107 | if curve == nil {
108 | return nil, errors.New("x509: unknown elliptic curve")
109 | }
110 |
111 | k := new(big.Int).SetBytes(privKey.PrivateKey)
112 | curveOrder := curve.Params().N
113 | if k.Cmp(curveOrder) >= 0 {
114 | return nil, errors.New("x509: invalid elliptic curve private key value")
115 | }
116 | priv := new(ecdsa.PrivateKey)
117 | priv.Curve = curve
118 | priv.D = k
119 |
120 | privateKey := make([]byte, (curveOrder.BitLen()+7)/8)
121 |
122 | // Some private keys have leading zero padding. This is invalid
123 | // according to [SEC1], but this code will ignore it.
124 | for len(privKey.PrivateKey) > len(privateKey) {
125 | if privKey.PrivateKey[0] != 0 {
126 | return nil, errors.New("x509: invalid private key length")
127 | }
128 | privKey.PrivateKey = privKey.PrivateKey[1:]
129 | }
130 |
131 | // Some private keys remove all leading zeros, this is also invalid
132 | // according to [SEC1] but since OpenSSL used to do this, we ignore
133 | // this too.
134 | copy(privateKey[len(privateKey)-len(privKey.PrivateKey):], privKey.PrivateKey)
135 | priv.X, priv.Y = curve.ScalarBaseMult(privateKey)
136 |
137 | return priv, nil
138 | }
139 | func marshalPKCS8PrivateKey(key interface{}) (der []byte, err error) {
140 | var privKey pkcs8
141 | switch key := key.(type) {
142 | case *rsa.PrivateKey:
143 | privKey.Algo.Algorithm = oidPublicKeyRSA
144 | // This is a NULL parameters value which is technically
145 | // superfluous, but most other code includes it.
146 | privKey.Algo.Parameters = asn1.RawValue{
147 | Tag: 5,
148 | }
149 | privKey.PrivateKey = x509.MarshalPKCS1PrivateKey(key)
150 | case *ecdsa.PrivateKey:
151 | privKey.Algo.Algorithm = oidPublicKeyECDSA
152 | namedCurveOID, ok := oidFromNamedCurve(key.Curve)
153 | if !ok {
154 | return nil, errors.New("go-pkcs12: unknown elliptic curve")
155 | }
156 | if privKey.Algo.Parameters.FullBytes, err = asn1.Marshal(namedCurveOID); err != nil {
157 | return nil, errors.New("go-pkcs12: failed to embed OID of named curve in PKCS#8: " + err.Error())
158 | }
159 | if privKey.PrivateKey, err =x509.MarshalECPrivateKey(key); err != nil {
160 | return nil, errors.New("go-pkcs12: failed to embed EC private key in PKCS#8: " + err.Error())
161 | }
162 | case *sm2.PrivateKey:
163 | privKey.Algo.Algorithm = oidPublicKeyECDSA
164 | namedCurveOID, ok := oidFromNamedCurve(key.Curve)
165 | if !ok {
166 | return nil, errors.New("go-pkcs12: unknown elliptic curve")
167 | }
168 | if privKey.Algo.Parameters.FullBytes, err = asn1.Marshal(namedCurveOID); err != nil {
169 | return nil, errors.New("go-pkcs12: failed to embed OID of named curve in PKCS#8: " + err.Error())
170 | }
171 | if privKey.PrivateKey, err = MarshalECPrivateKey(key); err != nil {
172 | return nil, errors.New("go-pkcs12: failed to embed EC private key in PKCS#8: " + err.Error())
173 | }
174 | default:
175 | return nil, errors.New("go-pkcs12: only RSA and ECDSA private keys supported")
176 | }
177 | return asn1.Marshal(privKey)
178 | }
179 | func MarshalECPrivateKey(key *sm2.PrivateKey) ([]byte, error) {
180 | oid, ok := oidFromNamedCurve(key.Curve)
181 | if !ok {
182 | return nil, errors.New("x509: unknown elliptic curve")
183 | }
184 |
185 | return MarshalPrivateKey(key, oid)
186 | }
187 | func MarshalPrivateKey(key *sm2.PrivateKey, oid asn1.ObjectIdentifier)([]byte,error){
188 | privateKeyBytes := key.D.Bytes()
189 | paddedPrivateKey := make([]byte, (key.Curve.Params().N.BitLen()+7)/8)
190 | copy(paddedPrivateKey[len(paddedPrivateKey)-len(privateKeyBytes):], privateKeyBytes)
191 | return asn1.Marshal(ecPrivateKey{
192 | Version: 1,
193 | PrivateKey: paddedPrivateKey,
194 | NamedCurveOID: oid,
195 | PublicKey: asn1.BitString{Bytes: elliptic.Marshal(key.Curve, key.X, key.Y)},
196 | })
197 | }
198 | type ecPrivateKey struct {
199 | Version int
200 | PrivateKey []byte
201 | NamedCurveOID asn1.ObjectIdentifier `asn1:"optional,explicit,tag:0"`
202 | PublicKey asn1.BitString `asn1:"optional,explicit,tag:1"`
203 | }
--------------------------------------------------------------------------------
/go.sum:
--------------------------------------------------------------------------------
1 | cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
2 | github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
3 | github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
4 | github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
5 | github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
6 | github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
7 | github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
8 | github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
9 | github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
10 | github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
11 | github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
12 | github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
13 | github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
14 | github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
15 | github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
16 | github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
17 | github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
18 | github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
19 | github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0=
20 | github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
21 | github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
22 | github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
23 | github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
24 | github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
25 | github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
26 | github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
27 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
28 | golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
29 | golang.org/x/crypto v0.0.0-20201012173705-84dcc777aaee h1:4yd7jl+vXjalO5ztz6Vc1VADv+S/80LGJmyl1ROJ2AI=
30 | golang.org/x/crypto v0.0.0-20201012173705-84dcc777aaee/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
31 | golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
32 | golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
33 | golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
34 | golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
35 | golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
36 | golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
37 | golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
38 | golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
39 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
40 | golang.org/x/net v0.0.0-20201010224723-4f7140c49acb h1:mUVeFHoDKis5nxCAzoAi7E8Ghb86EXh/RK6wtvJIqRY=
41 | golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
42 | golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
43 | golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
44 | golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
45 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
46 | golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
47 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
48 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
49 | golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f h1:+Nyd8tzPX9R7BWHguqsrbFdRx3WQ/1ib8I44HXV5yTA=
50 | golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
51 | golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
52 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
53 | golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
54 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
55 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
56 | golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
57 | golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
58 | golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
59 | golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
60 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
61 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
62 | google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
63 | google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
64 | google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
65 | google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55 h1:gSJIx1SDwno+2ElGhA4+qG2zF97qiUzTM+rQ0klBOcE=
66 | google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
67 | google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
68 | google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
69 | google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
70 | google.golang.org/grpc v1.31.0 h1:T7P4R73V3SSDPhH7WW7ATbfViLtmamH0DKrP3f9AuDI=
71 | google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
72 | google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
73 | google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
74 | google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
75 | google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
76 | google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
77 | google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM=
78 | google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
79 | honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
80 | honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
81 |
--------------------------------------------------------------------------------
/sm3/sm3.go:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright Suzhou Tongji Fintech Research Institute 2017 All Rights Reserved.
3 | Licensed under the Apache License, Version 2.0 (the "License");
4 | you may not use this file except in compliance with the License.
5 | You may obtain a copy of the License at
6 |
7 | http://www.apache.org/licenses/LICENSE-2.0
8 |
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
14 | */
15 |
16 | package sm3
17 |
18 | import (
19 | "encoding/binary"
20 | "hash"
21 | )
22 |
23 | type SM3 struct {
24 | digest [8]uint32 // digest represents the partial evaluation of V
25 | length uint64 // length of the message
26 | unhandleMsg []byte // uint8 //
27 | }
28 |
29 | func (sm3 *SM3) ff0(x, y, z uint32) uint32 { return x ^ y ^ z }
30 |
31 | func (sm3 *SM3) ff1(x, y, z uint32) uint32 { return (x & y) | (x & z) | (y & z) }
32 |
33 | func (sm3 *SM3) gg0(x, y, z uint32) uint32 { return x ^ y ^ z }
34 |
35 | func (sm3 *SM3) gg1(x, y, z uint32) uint32 { return (x & y) | (^x & z) }
36 |
37 | func (sm3 *SM3) p0(x uint32) uint32 { return x ^ sm3.leftRotate(x, 9) ^ sm3.leftRotate(x, 17) }
38 |
39 | func (sm3 *SM3) p1(x uint32) uint32 { return x ^ sm3.leftRotate(x, 15) ^ sm3.leftRotate(x, 23) }
40 |
41 | func (sm3 *SM3) leftRotate(x uint32, i uint32) uint32 { return x<<(i%32) | x>>(32-i%32) }
42 |
43 | func (sm3 *SM3) pad() []byte {
44 | msg := sm3.unhandleMsg
45 | msg = append(msg, 0x80) // Append '1'
46 | blockSize := 64 // Append until the resulting message length (in bits) is congruent to 448 (mod 512)
47 | for len(msg)%blockSize != 56 {
48 | msg = append(msg, 0x00)
49 | }
50 | // append message length
51 | msg = append(msg, uint8(sm3.length>>56&0xff))
52 | msg = append(msg, uint8(sm3.length>>48&0xff))
53 | msg = append(msg, uint8(sm3.length>>40&0xff))
54 | msg = append(msg, uint8(sm3.length>>32&0xff))
55 | msg = append(msg, uint8(sm3.length>>24&0xff))
56 | msg = append(msg, uint8(sm3.length>>16&0xff))
57 | msg = append(msg, uint8(sm3.length>>8&0xff))
58 | msg = append(msg, uint8(sm3.length>>0&0xff))
59 |
60 | if len(msg)%64 != 0 {
61 | panic("------SM3 Pad: error msgLen =")
62 | }
63 | return msg
64 | }
65 |
66 | func (sm3 *SM3) update(msg []byte) {
67 | var w [68]uint32
68 | var w1 [64]uint32
69 |
70 | a, b, c, d, e, f, g, h := sm3.digest[0], sm3.digest[1], sm3.digest[2], sm3.digest[3], sm3.digest[4], sm3.digest[5], sm3.digest[6], sm3.digest[7]
71 | for len(msg) >= 64 {
72 | for i := 0; i < 16; i++ {
73 | w[i] = binary.BigEndian.Uint32(msg[4*i : 4*(i+1)])
74 | }
75 | for i := 16; i < 68; i++ {
76 | w[i] = sm3.p1(w[i-16]^w[i-9]^sm3.leftRotate(w[i-3], 15)) ^ sm3.leftRotate(w[i-13], 7) ^ w[i-6]
77 | }
78 | for i := 0; i < 64; i++ {
79 | w1[i] = w[i] ^ w[i+4]
80 | }
81 | A, B, C, D, E, F, G, H := a, b, c, d, e, f, g, h
82 | for i := 0; i < 16; i++ {
83 | SS1 := sm3.leftRotate(sm3.leftRotate(A, 12)+E+sm3.leftRotate(0x79cc4519, uint32(i)), 7)
84 | SS2 := SS1 ^ sm3.leftRotate(A, 12)
85 | TT1 := sm3.ff0(A, B, C) + D + SS2 + w1[i]
86 | TT2 := sm3.gg0(E, F, G) + H + SS1 + w[i]
87 | D = C
88 | C = sm3.leftRotate(B, 9)
89 | B = A
90 | A = TT1
91 | H = G
92 | G = sm3.leftRotate(F, 19)
93 | F = E
94 | E = sm3.p0(TT2)
95 | }
96 | for i := 16; i < 64; i++ {
97 | SS1 := sm3.leftRotate(sm3.leftRotate(A, 12)+E+sm3.leftRotate(0x7a879d8a, uint32(i)), 7)
98 | SS2 := SS1 ^ sm3.leftRotate(A, 12)
99 | TT1 := sm3.ff1(A, B, C) + D + SS2 + w1[i]
100 | TT2 := sm3.gg1(E, F, G) + H + SS1 + w[i]
101 | D = C
102 | C = sm3.leftRotate(B, 9)
103 | B = A
104 | A = TT1
105 | H = G
106 | G = sm3.leftRotate(F, 19)
107 | F = E
108 | E = sm3.p0(TT2)
109 | }
110 | a ^= A
111 | b ^= B
112 | c ^= C
113 | d ^= D
114 | e ^= E
115 | f ^= F
116 | g ^= G
117 | h ^= H
118 | msg = msg[64:]
119 | }
120 | sm3.digest[0], sm3.digest[1], sm3.digest[2], sm3.digest[3], sm3.digest[4], sm3.digest[5], sm3.digest[6], sm3.digest[7] = a, b, c, d, e, f, g, h
121 | }
122 | func (sm3 *SM3) update2(msg []byte,) [8]uint32 {
123 | var w [68]uint32
124 | var w1 [64]uint32
125 |
126 | a, b, c, d, e, f, g, h := sm3.digest[0], sm3.digest[1], sm3.digest[2], sm3.digest[3], sm3.digest[4], sm3.digest[5], sm3.digest[6], sm3.digest[7]
127 | for len(msg) >= 64 {
128 | for i := 0; i < 16; i++ {
129 | w[i] = binary.BigEndian.Uint32(msg[4*i : 4*(i+1)])
130 | }
131 | for i := 16; i < 68; i++ {
132 | w[i] = sm3.p1(w[i-16]^w[i-9]^sm3.leftRotate(w[i-3], 15)) ^ sm3.leftRotate(w[i-13], 7) ^ w[i-6]
133 | }
134 | for i := 0; i < 64; i++ {
135 | w1[i] = w[i] ^ w[i+4]
136 | }
137 | A, B, C, D, E, F, G, H := a, b, c, d, e, f, g, h
138 | for i := 0; i < 16; i++ {
139 | SS1 := sm3.leftRotate(sm3.leftRotate(A, 12)+E+sm3.leftRotate(0x79cc4519, uint32(i)), 7)
140 | SS2 := SS1 ^ sm3.leftRotate(A, 12)
141 | TT1 := sm3.ff0(A, B, C) + D + SS2 + w1[i]
142 | TT2 := sm3.gg0(E, F, G) + H + SS1 + w[i]
143 | D = C
144 | C = sm3.leftRotate(B, 9)
145 | B = A
146 | A = TT1
147 | H = G
148 | G = sm3.leftRotate(F, 19)
149 | F = E
150 | E = sm3.p0(TT2)
151 | }
152 | for i := 16; i < 64; i++ {
153 | SS1 := sm3.leftRotate(sm3.leftRotate(A, 12)+E+sm3.leftRotate(0x7a879d8a, uint32(i)), 7)
154 | SS2 := SS1 ^ sm3.leftRotate(A, 12)
155 | TT1 := sm3.ff1(A, B, C) + D + SS2 + w1[i]
156 | TT2 := sm3.gg1(E, F, G) + H + SS1 + w[i]
157 | D = C
158 | C = sm3.leftRotate(B, 9)
159 | B = A
160 | A = TT1
161 | H = G
162 | G = sm3.leftRotate(F, 19)
163 | F = E
164 | E = sm3.p0(TT2)
165 | }
166 | a ^= A
167 | b ^= B
168 | c ^= C
169 | d ^= D
170 | e ^= E
171 | f ^= F
172 | g ^= G
173 | h ^= H
174 | msg = msg[64:]
175 | }
176 | var digest [8]uint32
177 | digest[0], digest[1], digest[2], digest[3], digest[4], digest[5], digest[6], digest[7] = a, b, c, d, e, f, g, h
178 | return digest
179 | }
180 |
181 | // 创建哈希计算实例
182 | func New() hash.Hash {
183 | var sm3 SM3
184 |
185 | sm3.Reset()
186 | return &sm3
187 | }
188 |
189 | // BlockSize returns the hash's underlying block size.
190 | // The Write method must be able to accept any amount
191 | // of data, but it may operate more efficiently if all writes
192 | // are a multiple of the block size.
193 | func (sm3 *SM3) BlockSize() int { return 64 }
194 |
195 | // Size returns the number of bytes Sum will return.
196 | func (sm3 *SM3) Size() int { return 32 }
197 |
198 | // Reset clears the internal state by zeroing bytes in the state buffer.
199 | // This can be skipped for a newly-created hash state; the default zero-allocated state is correct.
200 | func (sm3 *SM3) Reset() {
201 | // Reset digest
202 | sm3.digest[0] = 0x7380166f
203 | sm3.digest[1] = 0x4914b2b9
204 | sm3.digest[2] = 0x172442d7
205 | sm3.digest[3] = 0xda8a0600
206 | sm3.digest[4] = 0xa96f30bc
207 | sm3.digest[5] = 0x163138aa
208 | sm3.digest[6] = 0xe38dee4d
209 | sm3.digest[7] = 0xb0fb0e4e
210 |
211 | sm3.length = 0 // Reset numberic states
212 | sm3.unhandleMsg = []byte{}
213 | }
214 |
215 | // Write (via the embedded io.Writer interface) adds more data to the running hash.
216 | // It never returns an error.
217 | func (sm3 *SM3) Write(p []byte) (int, error) {
218 | toWrite := len(p)
219 | sm3.length += uint64(len(p) * 8)
220 | msg := append(sm3.unhandleMsg, p...)
221 | nblocks := len(msg) / sm3.BlockSize()
222 | sm3.update(msg)
223 | // Update unhandleMsg
224 | sm3.unhandleMsg = msg[nblocks*sm3.BlockSize():]
225 |
226 | return toWrite, nil
227 | }
228 |
229 | // 返回SM3哈希算法摘要值
230 | // Sum appends the current hash to b and returns the resulting slice.
231 | // It does not change the underlying hash state.
232 | func (sm3 *SM3) Sum(in []byte) []byte {
233 | _, _ = sm3.Write(in)
234 | msg := sm3.pad()
235 | //Finalize
236 | digest := sm3.update2(msg)
237 |
238 | // save hash to in
239 | needed := sm3.Size()
240 | if cap(in)-len(in) < needed {
241 | newIn := make([]byte, len(in), len(in)+needed)
242 | copy(newIn, in)
243 | in = newIn
244 | }
245 | out := in[len(in) : len(in)+needed]
246 | for i := 0; i < 8; i++ {
247 | binary.BigEndian.PutUint32(out[i*4:], digest[i])
248 | }
249 | return out
250 |
251 | }
252 |
253 | func Sm3Sum(data []byte) []byte {
254 | var sm3 SM3
255 |
256 | sm3.Reset()
257 | _, _ = sm3.Write(data)
258 | return sm3.Sum(nil)
259 | }
260 |
--------------------------------------------------------------------------------
/x509/utils.go:
--------------------------------------------------------------------------------
1 | package x509
2 |
3 | import (
4 | "bytes"
5 | "crypto"
6 | "crypto/rand"
7 | "crypto/rsa"
8 | "crypto/x509"
9 | "encoding/asn1"
10 | "encoding/hex"
11 | "encoding/pem"
12 | "errors"
13 | "math/big"
14 |
15 | "github.com/tjfoc/gmsm/sm2"
16 | )
17 |
18 | func ReadPrivateKeyFromPem(privateKeyPem []byte, pwd []byte) (*sm2.PrivateKey, error) {
19 | var block *pem.Block
20 | block, _ = pem.Decode(privateKeyPem)
21 | if block == nil {
22 | return nil, errors.New("failed to decode private key")
23 | }
24 | priv, err := ParsePKCS8PrivateKey(block.Bytes, pwd)
25 | return priv, err
26 | }
27 |
28 | func WritePrivateKeyToPem(key *sm2.PrivateKey, pwd []byte) ([]byte, error) {
29 | var block *pem.Block
30 | der, err := MarshalSm2PrivateKey(key, pwd) //Convert private key to DER format
31 | if err != nil {
32 | return nil, err
33 | }
34 | if pwd != nil {
35 | block = &pem.Block{
36 | Type: "ENCRYPTED PRIVATE KEY",
37 | Bytes: der,
38 | }
39 | } else {
40 | block = &pem.Block{
41 | Type: "PRIVATE KEY",
42 | Bytes: der,
43 | }
44 | }
45 | certPem := pem.EncodeToMemory(block)
46 | return certPem, nil
47 | }
48 |
49 | func ReadPublicKeyFromPem(publicKeyPem []byte) (*sm2.PublicKey, error) {
50 | block, _ := pem.Decode(publicKeyPem)
51 | if block == nil || block.Type != "PUBLIC KEY" {
52 | return nil, errors.New("failed to decode public key")
53 | }
54 | return ParseSm2PublicKey(block.Bytes)
55 | }
56 |
57 | func WritePublicKeyToPem(key *sm2.PublicKey) ([]byte, error) {
58 | der, err := MarshalSm2PublicKey(key) //Convert publick key to DER format
59 | if err != nil {
60 | return nil, err
61 | }
62 | block := &pem.Block{
63 | Type: "PUBLIC KEY",
64 | Bytes: der,
65 | }
66 | certPem := pem.EncodeToMemory(block)
67 | return certPem, nil
68 | }
69 |
70 | //DHex是sm2私钥的真正关键数值
71 | func ReadPrivateKeyFromHex(Dhex string) (*sm2.PrivateKey,error) {
72 | c := sm2.P256Sm2()
73 | d,err:=hex.DecodeString(Dhex)
74 | if err!=nil{
75 | return nil,err
76 | }
77 | k:= new(big.Int).SetBytes(d)
78 | params := c.Params()
79 | one := new(big.Int).SetInt64(1)
80 | n := new(big.Int).Sub(params.N, one)
81 | if k.Cmp(n)>=0{
82 | return nil,errors.New("privateKey's D is overflow.")
83 | }
84 | priv := new(sm2.PrivateKey)
85 | priv.PublicKey.Curve = c
86 | priv.D = k
87 | priv.PublicKey.X, priv.PublicKey.Y = c.ScalarBaseMult(k.Bytes())
88 | return priv,nil
89 | }
90 |
91 |
92 |
93 | func WritePrivateKeyToHex(key *sm2.PrivateKey) string {
94 | return key.D.Text(16)
95 | }
96 |
97 | func ReadPublicKeyFromHex(Qhex string) (*sm2.PublicKey, error) {
98 | q,err:=hex.DecodeString(Qhex)
99 | if err!=nil{
100 | return nil,err
101 | }
102 | if len(q)==65&&q[0]==byte(0x04){
103 | q=q[1:]
104 | }
105 | if len(q)!=64{
106 | return nil,errors.New("publicKey is not uncompressed.")
107 | }
108 | pub := new(sm2.PublicKey)
109 | pub.Curve = sm2.P256Sm2()
110 | pub.X = new(big.Int).SetBytes(q[:32])
111 | pub.Y = new(big.Int).SetBytes(q[32:])
112 | return pub, nil
113 | }
114 |
115 |
116 | func WritePublicKeyToHex(key *sm2.PublicKey) string {
117 | x := key.X.Bytes()
118 | y := key.Y.Bytes()
119 | if n := len(x); n < 32 {
120 | x = append(zeroByteSlice()[:32-n], x...)
121 | }
122 | if n := len(y); n < 32 {
123 | y = append(zeroByteSlice()[:32-n], y...)
124 | }
125 | c := []byte{}
126 | c = append(c, x...)
127 | c = append(c, y...)
128 | c = append([]byte{0x04}, c...)
129 | return hex.EncodeToString(c)
130 | }
131 |
132 |
133 | func ReadCertificateRequestFromPem(certPem []byte) (*CertificateRequest, error) {
134 | block, _ := pem.Decode(certPem)
135 | if block == nil {
136 | return nil, errors.New("failed to decode certificate request")
137 | }
138 | return ParseCertificateRequest(block.Bytes)
139 | }
140 |
141 | func CreateCertificateRequestToPem(template *CertificateRequest, signer crypto.Signer) ([]byte, error) {
142 | der, err := CreateCertificateRequest(rand.Reader, template, signer)
143 | if err != nil {
144 | return nil, err
145 | }
146 | block := &pem.Block{
147 | Type: "CERTIFICATE REQUEST",
148 | Bytes: der,
149 | }
150 | certPem := pem.EncodeToMemory(block)
151 | return certPem, nil
152 | }
153 |
154 | func ReadCertificateFromPem(certPem []byte) (*Certificate, error) {
155 | block, _ := pem.Decode(certPem)
156 | if block == nil {
157 | return nil, errors.New("failed to decode certificate request")
158 | }
159 | return ParseCertificate(block.Bytes)
160 | }
161 |
162 | // CreateCertificate creates a new certificate based on a template. The
163 | // following members of template are used: SerialNumber, Subject, NotBefore,
164 | // NotAfter, KeyUsage, ExtKeyUsage, UnknownExtKeyUsage, BasicConstraintsValid,
165 | // IsCA, MaxPathLen, SubjectKeyId, DNSNames, PermittedDNSDomainsCritical,
166 | // PermittedDNSDomains, SignatureAlgorithm.
167 | //
168 | // The certificate is signed by parent. If parent is equal to template then the
169 | // certificate is self-signed. The parameter pub is the public key of the
170 | // signee and priv is the private key of the signer.
171 | //
172 | // The returned slice is the certificate in DER encoding.
173 | //
174 | // All keys types that are implemented via crypto.Signer are supported (This
175 | // includes *rsa.PublicKey and *ecdsa.PublicKey.)
176 | func CreateCertificate(template, parent *Certificate, publicKey *sm2.PublicKey, signer crypto.Signer) ([]byte, error) {
177 | if template.SerialNumber == nil {
178 | return nil, errors.New("x509: no SerialNumber given")
179 | }
180 |
181 | hashFunc, signatureAlgorithm, err := signingParamsForPublicKey(signer.Public(), template.SignatureAlgorithm)
182 | if err != nil {
183 | return nil, err
184 | }
185 |
186 | publicKeyBytes, publicKeyAlgorithm, err := marshalPublicKey(publicKey)
187 | if err != nil {
188 | return nil, err
189 | }
190 |
191 | asn1Issuer, err := subjectBytes(parent)
192 | if err != nil {
193 | return nil, err
194 | }
195 |
196 | asn1Subject, err := subjectBytes(template)
197 | if err != nil {
198 | return nil, err
199 | }
200 |
201 | if !bytes.Equal(asn1Issuer, asn1Subject) && len(parent.SubjectKeyId) > 0 {
202 | template.AuthorityKeyId = parent.SubjectKeyId
203 | }
204 |
205 | extensions, err := buildExtensions(template)
206 | if err != nil {
207 | return nil, err
208 | }
209 | encodedPublicKey := asn1.BitString{BitLength: len(publicKeyBytes) * 8, Bytes: publicKeyBytes}
210 | c := tbsCertificate{
211 | Version: 2,
212 | SerialNumber: template.SerialNumber,
213 | SignatureAlgorithm: signatureAlgorithm,
214 | Issuer: asn1.RawValue{FullBytes: asn1Issuer},
215 | Validity: validity{template.NotBefore.UTC(), template.NotAfter.UTC()},
216 | Subject: asn1.RawValue{FullBytes: asn1Subject},
217 | PublicKey: publicKeyInfo{nil, publicKeyAlgorithm, encodedPublicKey},
218 | Extensions: extensions,
219 | }
220 |
221 | tbsCertContents, err := asn1.Marshal(c)
222 | if err != nil {
223 | return nil, err
224 | }
225 |
226 | c.Raw = tbsCertContents
227 |
228 | digest := tbsCertContents
229 | switch template.SignatureAlgorithm {
230 | case SM2WithSM3, SM2WithSHA1, SM2WithSHA256:
231 | break
232 | default:
233 | h := hashFunc.New()
234 | h.Write(tbsCertContents)
235 | digest = h.Sum(nil)
236 | }
237 |
238 | var signerOpts crypto.SignerOpts
239 | signerOpts = hashFunc
240 | if template.SignatureAlgorithm != 0 && template.SignatureAlgorithm.isRSAPSS() {
241 | signerOpts = &rsa.PSSOptions{
242 | SaltLength: rsa.PSSSaltLengthEqualsHash,
243 | Hash: crypto.Hash(hashFunc),
244 | }
245 | }
246 |
247 | var signature []byte
248 | signature, err = signer.Sign(rand.Reader, digest, signerOpts)
249 | if err != nil {
250 | return nil, err
251 | }
252 | return asn1.Marshal(certificate{
253 | nil,
254 | c,
255 | signatureAlgorithm,
256 | asn1.BitString{Bytes: signature, BitLength: len(signature) * 8},
257 | })
258 | }
259 |
260 | // CreateCertificateToPem creates a new certificate based on a template and
261 | // encodes it to PEM format. It uses CreateCertificate to create certificate
262 | // and returns its PEM format.
263 | func CreateCertificateToPem(template, parent *Certificate, pubKey *sm2.PublicKey, signer crypto.Signer) ([]byte, error) {
264 | der, err := CreateCertificate(template, parent, pubKey, signer)
265 | if err != nil {
266 | return nil, err
267 | }
268 | block := &pem.Block{
269 | Type: "CERTIFICATE",
270 | Bytes: der,
271 | }
272 | certPem := pem.EncodeToMemory(block)
273 | return certPem, nil
274 | }
275 |
276 | func ParseSm2CertifateToX509(asn1data []byte) (*x509.Certificate, error) {
277 | sm2Cert, err := ParseCertificate(asn1data)
278 | if err != nil {
279 | return nil, err
280 | }
281 | return sm2Cert.ToX509Certificate(), nil
282 | }
283 | // 32byte
284 | func zeroByteSlice() []byte {
285 | return []byte{
286 | 0, 0, 0, 0,
287 | 0, 0, 0, 0,
288 | 0, 0, 0, 0,
289 | 0, 0, 0, 0,
290 | 0, 0, 0, 0,
291 | 0, 0, 0, 0,
292 | 0, 0, 0, 0,
293 | 0, 0, 0, 0,
294 | }
295 | }
296 |
--------------------------------------------------------------------------------
/sm4/sm4_gcm.go:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright Hyperledger-TWGC All Rights Reserved.
3 | Licensed under the Apache License, Version 2.0 (the "License");
4 | you may not use this file except in compliance with the License.
5 | You may obtain a copy of the License at
6 |
7 | http://www.apache.org/licenses/LICENSE-2.0
8 |
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
14 |
15 | writed by Zhiwei Yan, 2020 Oct
16 | */
17 |
18 | package sm4
19 |
20 | import (
21 | "errors"
22 | "strconv"
23 | )
24 |
25 | // Sm4GCM SM4 GCM 加解密模式
26 | // Paper: The Galois/Counter Mode of Operation (GCM) David A. Mcgrew,John Viega .2004.
27 | // key: 对称加密密钥
28 | // IV: IV向量
29 | // in:
30 | // A: 附加的可鉴别数据(ADD)
31 | // mode: true - 加密; false - 解密验证
32 | //
33 | // return: 密文C, 鉴别标签T, 错误
34 | func Sm4GCM(key []byte, IV, in, A []byte, mode bool) ([]byte, []byte, error) {
35 | if len(key) != BlockSize {
36 | return nil, nil, errors.New("SM4: invalid key size " + strconv.Itoa(len(key)))
37 | }
38 | if mode {
39 | C, T := GCMEncrypt(key, IV, in, A)
40 | return C, T, nil
41 | } else {
42 | P, _T := GCMDecrypt(key, IV, in, A)
43 | return P, _T, nil
44 | }
45 | }
46 |
47 | // GetH 对“0”分组的加密得到 GHASH泛杂凑函数的子密钥
48 | // key: 对称密钥
49 | // return: GHASH泛杂凑函数的子密钥
50 | func GetH(key []byte) (H []byte) {
51 | c, err := NewCipher(key)
52 | if err != nil {
53 | panic(err)
54 | }
55 |
56 | zores := make([]byte, BlockSize)
57 | H = make([]byte, BlockSize)
58 | c.Encrypt(H, zores)
59 | return H
60 | }
61 |
62 | //ut = a + b
63 | func addition(a, b []byte) (out []byte) {
64 | Len := len(a)
65 | if Len != len(b) {
66 | return nil
67 | }
68 | out = make([]byte, Len)
69 | for i := 0; i < Len; i++ {
70 | out[i] = a[i] ^ b[i]
71 | }
72 | return out
73 | }
74 |
75 | func Rightshift(V []byte) {
76 | n := len(V)
77 | for i := n - 1; i >= 0; i-- {
78 | V[i] = V[i] >> 1
79 | if i != 0 {
80 | V[i] = ((V[i-1] & 0x01) << 7) | V[i]
81 | }
82 | }
83 | }
84 |
85 | func findYi(Y []byte, index int) int {
86 | var temp byte
87 | i := uint(index)
88 | temp = Y[i/8]
89 | temp = temp >> (7 - i%8)
90 | if temp&0x01 == 1 {
91 | return 1
92 | } else {
93 | return 0
94 | }
95 | }
96 |
97 | func multiplication(X, Y []byte) (Z []byte) {
98 |
99 | R := make([]byte, BlockSize)
100 | R[0] = 0xe1
101 | Z = make([]byte, BlockSize)
102 | V := make([]byte, BlockSize)
103 | copy(V, X)
104 | for i := 0; i <= 127; i++ {
105 | if findYi(Y, i) == 1 {
106 | Z = addition(Z, V)
107 | }
108 | if V[BlockSize-1]&0x01 == 0 {
109 | Rightshift(V)
110 | } else {
111 | Rightshift(V)
112 | V = addition(V, R)
113 | }
114 | }
115 | return Z
116 | }
117 |
118 | func GHASH(H []byte, A []byte, C []byte) (X []byte) {
119 |
120 | calculm_v := func(m, v int) (int, int) {
121 | if m == 0 && v != 0 {
122 | m = 1
123 | v = v * 8
124 | } else if m != 0 && v == 0 {
125 | v = BlockSize * 8
126 | } else if m != 0 && v != 0 {
127 | m = m + 1
128 | v = v * 8
129 | } else { //m==0 && v==0
130 | m = 1
131 | v = 0
132 | }
133 | return m, v
134 | }
135 | m := len(A) / BlockSize
136 | v := len(A) % BlockSize
137 | m, v = calculm_v(m, v)
138 |
139 | n := len(C) / BlockSize
140 | u := (len(C) % BlockSize)
141 | n, u = calculm_v(n, u)
142 |
143 | //i=0
144 | X = make([]byte, BlockSize*(m+n+2)) //X0 = 0
145 | for i := 0; i < BlockSize; i++ {
146 | X[i] = 0x00
147 | }
148 |
149 | //i=1...m-1
150 | for i := 1; i <= m-1; i++ {
151 | copy(X[i*BlockSize:i*BlockSize+BlockSize], multiplication(addition(X[(i-1)*BlockSize:(i-1)*BlockSize+BlockSize], A[(i-1)*BlockSize:(i-1)*BlockSize+BlockSize]), H)) //A 1-->m-1 对于数组来说是 0-->m-2
152 | }
153 |
154 | //i=m
155 | zeros := make([]byte, (128-v)/8)
156 | Am := make([]byte, v/8)
157 | copy(Am[:], A[(m-1)*BlockSize:])
158 | Am = append(Am, zeros...)
159 | copy(X[m*BlockSize:m*BlockSize+BlockSize], multiplication(addition(X[(m-1)*BlockSize:(m-1)*BlockSize+BlockSize], Am), H))
160 |
161 | //i=m+1...m+n-1
162 | for i := m + 1; i <= (m + n - 1); i++ {
163 | copy(X[i*BlockSize:i*BlockSize+BlockSize], multiplication(addition(X[(i-1)*BlockSize:(i-1)*BlockSize+BlockSize], C[(i-m-1)*BlockSize:(i-m-1)*BlockSize+BlockSize]), H))
164 | }
165 |
166 | //i=m+n
167 | zeros = make([]byte, (128-u)/8)
168 | Cn := make([]byte, u/8)
169 | copy(Cn[:], C[(n-1)*BlockSize:])
170 | Cn = append(Cn, zeros...)
171 | copy(X[(m+n)*BlockSize:(m+n)*BlockSize+BlockSize], multiplication(addition(X[(m+n-1)*BlockSize:(m+n-1)*BlockSize+BlockSize], Cn), H))
172 |
173 | //i=m+n+1
174 | var lenAB []byte
175 | calculateLenToBytes := func(len int) []byte {
176 | data := make([]byte, 8)
177 | data[0] = byte((len >> 56) & 0xff)
178 | data[1] = byte((len >> 48) & 0xff)
179 | data[2] = byte((len >> 40) & 0xff)
180 | data[3] = byte((len >> 32) & 0xff)
181 | data[4] = byte((len >> 24) & 0xff)
182 | data[5] = byte((len >> 16) & 0xff)
183 | data[6] = byte((len >> 8) & 0xff)
184 | data[7] = byte((len >> 0) & 0xff)
185 | return data
186 | }
187 | lenAB = append(lenAB, calculateLenToBytes(len(A))...)
188 | lenAB = append(lenAB, calculateLenToBytes(len(C))...)
189 | copy(X[(m+n+1)*BlockSize:(m+n+1)*BlockSize+BlockSize], multiplication(addition(X[(m+n)*BlockSize:(m+n)*BlockSize+BlockSize], lenAB), H))
190 | return X[(m+n+1)*BlockSize : (m+n+1)*BlockSize+BlockSize]
191 | }
192 |
193 | // GetY0 生成初始的计数器时钟J0
194 | //
195 | // H: GHASH自密钥
196 | // IV: IV向量
197 | // return: 初始的计数器时钟(J0)
198 | func GetY0(H, IV []byte) []byte {
199 | if len(IV)*8 == 96 {
200 | zero31one1 := []byte{0x00, 0x00, 0x00, 0x01}
201 | IV = append(IV, zero31one1...)
202 | return IV
203 | } else {
204 | return GHASH(H, []byte{}, IV)
205 | }
206 | }
207 |
208 | func incr(n int, Y_i []byte) (Y_ii []byte) {
209 |
210 | Y_ii = make([]byte, BlockSize*n)
211 | copy(Y_ii, Y_i)
212 |
213 | addYone := func(yi, yii []byte) {
214 | copy(yii[:], yi[:])
215 |
216 | Len := len(yi)
217 | var rc byte = 0x00
218 | for i := Len - 1; i >= 0; i-- {
219 | if i == Len-1 {
220 | if yii[i] < 0xff {
221 | yii[i] = yii[i] + 0x01
222 | rc = 0x00
223 | } else {
224 | yii[i] = 0x00
225 | rc = 0x01
226 | }
227 | } else {
228 | if yii[i]+rc < 0xff {
229 | yii[i] = yii[i] + rc
230 | rc = 0x00
231 | } else {
232 | yii[i] = 0x00
233 | rc = 0x01
234 | }
235 | }
236 | }
237 | }
238 | for i := 1; i < n; i++ { //2^32
239 | addYone(Y_ii[(i-1)*BlockSize:(i-1)*BlockSize+BlockSize], Y_ii[i*BlockSize:i*BlockSize+BlockSize])
240 | }
241 | return Y_ii
242 | }
243 |
244 | func MSB(len int, S []byte) (out []byte) {
245 | return S[:len/8]
246 | }
247 |
248 | // GCMEncrypt 可鉴别加密函数 (GCM-AE(k))
249 | // K: 对称密钥
250 | // IV: IV向量
251 | // P: 明文
252 | // A: 附加的鉴别数据
253 | //
254 | // return: 密文, 鉴别标签
255 | func GCMEncrypt(K, IV, P, A []byte) (C, T []byte) {
256 | calculm_v := func(m, v int) (int, int) {
257 | if m == 0 && v != 0 {
258 | m = 1
259 | v = v * 8
260 | } else if m != 0 && v == 0 {
261 | v = BlockSize * 8
262 | } else if m != 0 && v != 0 {
263 | m = m + 1
264 | v = v * 8
265 | } else { //m==0 && v==0
266 | m = 1
267 | v = 0
268 | }
269 | return m, v
270 | }
271 | n := len(P) / BlockSize
272 | u := len(P) % BlockSize
273 | n, u = calculm_v(n, u)
274 |
275 | // a) 通过对“0”分组的加密得到 GHASH泛杂凑函数的子密钥
276 | H := GetH(K)
277 |
278 | Y0 := GetY0(H, IV)
279 |
280 | Y := make([]byte, BlockSize*(n+1))
281 | Y = incr(n+1, Y0)
282 | c, err := NewCipher(K)
283 | if err != nil {
284 | panic(err)
285 | }
286 | Enc := make([]byte, BlockSize)
287 | C = make([]byte, len(P))
288 |
289 | //i=1...n-1
290 | for i := 1; i <= n-1; i++ {
291 | c.Encrypt(Enc, Y[i*BlockSize:i*BlockSize+BlockSize])
292 |
293 | copy(C[(i-1)*BlockSize:(i-1)*BlockSize+BlockSize], addition(P[(i-1)*BlockSize:(i-1)*BlockSize+BlockSize], Enc))
294 | }
295 |
296 | //i=n
297 | c.Encrypt(Enc, Y[n*BlockSize:n*BlockSize+BlockSize])
298 | out := MSB(u, Enc)
299 | copy(C[(n-1)*BlockSize:], addition(P[(n-1)*BlockSize:], out))
300 |
301 | c.Encrypt(Enc, Y0)
302 |
303 | t := 128
304 | T = MSB(t, addition(Enc, GHASH(H, A, C)))
305 | return C, T
306 | }
307 |
308 | func GCMDecrypt(K, IV, C, A []byte) (P, _T []byte) {
309 | calculm_v := func(m, v int) (int, int) {
310 | if m == 0 && v != 0 {
311 | m = 1
312 | v = v * 8
313 | } else if m != 0 && v == 0 {
314 | v = BlockSize * 8
315 | } else if m != 0 && v != 0 {
316 | m = m + 1
317 | v = v * 8
318 | } else { //m==0 && v==0
319 | m = 1
320 | v = 0
321 | }
322 | return m, v
323 | }
324 |
325 | H := GetH(K)
326 |
327 | Y0 := GetY0(H, IV)
328 |
329 | Enc := make([]byte, BlockSize)
330 | c, err := NewCipher(K)
331 | if err != nil {
332 | panic(err)
333 | }
334 | c.Encrypt(Enc, Y0)
335 | t := 128
336 | _T = MSB(t, addition(Enc, GHASH(H, A, C)))
337 |
338 | n := len(C) / BlockSize
339 | u := len(C) % BlockSize
340 | n, u = calculm_v(n, u)
341 | Y := make([]byte, BlockSize*(n+1))
342 | Y = incr(n+1, Y0)
343 |
344 | P = make([]byte, BlockSize*n)
345 | for i := 1; i <= n; i++ {
346 | c.Encrypt(Enc, Y[i*BlockSize:i*BlockSize+BlockSize])
347 | copy(P[(i-1)*BlockSize:(i-1)*BlockSize+BlockSize], addition(C[(i-1)*BlockSize:(i-1)*BlockSize+BlockSize], Enc))
348 | }
349 |
350 | c.Encrypt(Enc, Y[n*BlockSize:n*BlockSize+BlockSize])
351 | out := MSB(u, Enc)
352 | copy(P[(n-1)*BlockSize:], addition(C[(n-1)*BlockSize:], out))
353 |
354 | return P, _T
355 | }
356 |
--------------------------------------------------------------------------------
/gmtls/websvr/README.md:
--------------------------------------------------------------------------------
1 | # TLS/GMSSL 服务端协议自适应
2 |
3 |
4 |
5 | - [TLS/GMSSL 服务端协议自适应](#tlsgmssl-服务端协议自适应)
6 | - [服务端 GMSSL/TLS 工作逻辑](#服务端-gmssltls-工作逻辑)
7 | - [GMSSL/TLS 自动切换模式](#gmssltls-自动切换模式)
8 | - [TCLP 双向身份认证](#tclp-双向身份认证)
9 | - [服务端配置](#服务端配置)
10 | - [客户端配置](#客户端配置)
11 | - [国密HTTPS客户端](#国密https客户端)
12 | - [HTTPS 单向身份认证](#https-单向身份认证)
13 | - [HTTPS 双向身份认证](#https-双向身份认证)
14 | - [TLCP GCM模式](#tlcp-gcm模式)
15 | - [客户端 GCM配置](#客户端-gcm配置)
16 | - [关于 TLCP AEAD随机数](#关于-tlcp-aead随机数)
17 |
18 |
19 |
20 |
21 | 目录结构说明:
22 |
23 | ```
24 | ├─certs // 证书以及密钥
25 | ├─websvr_test //HTTP服务端/客户端测试Demo
26 | └─websvr //协议自适应实现
27 | ```
28 |
29 | ## 服务端 GMSSL/TLS 工作逻辑
30 |
31 | 
32 |
33 |
34 | 通过配置`gmtls.Config` 对象提供自动切换相关的配置,创建`gmtls.Conn`。
35 |
36 | 在对`gmtls.Conn`的`Read/Wirte`时将会触发握手行为`HandShake`。
37 |
38 | `HandShake`会根据用户配置参数,判断需要使用 GMSSL、TLS、GMSSL/TLS 三种工作模式中的哪一种,
39 | 然后进入到相应的工作模式中运行。
40 |
41 | - **TLS工作模式**:
42 | - 运行`serverHandshake` 进入TLS握手。
43 | - 创建TLS握手上下文`serverHandshakeState`。
44 | - 读取并处理 来自于客户端的ClientHello 消息。
45 | - 进入 TLS握手流程。
46 | - **GMSSL工作模式**:
47 | - 运行`serverHandshakeGM` 进入GMSSL握手。
48 | - 创建TLS握手上下文`serverHandshakeStateGM`。
49 | - 读取并处理 来自于客户端的ClientHello 消息。
50 | - 进入 GMSSL握手流程。
51 | - **GMSSL/TLS工作模式**:
52 | - 运行`serverHandshakeAutoSwitch` 进入自动切换的握手模式。
53 | - 读取来自于客户端的ClientHello 消息。
54 | - 分析处理ClientHello,根据客户端协议版本。
55 | - 根据协议版本,选择使用具体握手方式:
56 | - GMSSL: 创建上下文`serverHandshakeStateGM`,进入GMSSL握手流程。
57 | - TLS: 创建上下文`serverHandshakeState`,进入TLS握手流程。
58 |
59 |
60 | 在GMSSL/TLS模式的服务端运行过程中,如何根据客户端版本选择需要使用的证书以及密钥?
61 |
62 | 自动切换模式,同时需要为服务端提供2份证书与密钥对(一份用于标准的TLS、一份用于GMSSL),
63 | 在运行过程需要使用到`gmtls.Config#GetCertificate`方法来根据客户端的版本选择出合适的
64 | 证书密钥对,即在客户端版本是GMSSL的时候返回SM2签名证书密钥对;在客户端版本是标准的TLS时
65 | 返还RSA/ECC的证书密钥对,以次来动态适应不同客户端的连接需求。
66 | 针对于GMSSL特殊的双证书需求,特别为`gmtls.Config`增加了一个方法`gmtls.Config#GetKECertificate`
67 | 通过该方法来提供GMSSL密钥交换过程中使用密钥对。
68 |
69 | 更多细节实现见: [auto_handshake_server](../auto_handshake_server.go)
70 |
71 | ## GMSSL/TLS 自动切换模式
72 |
73 | 快速开始:
74 |
75 | 1. 准备 RSA、SM2签名、SM2加密,证书以及密钥对。
76 | 2. 调用`gmtls.NewBasicAutoSwitchConfig`构造基础的配置对象。
77 | 3. Use it.
78 |
79 | ```go
80 | func main() {
81 | config, err := gmtls.NewBasicAutoSwitchConfig(&sigCert, &encCert, &rsaKeypair)
82 | if err != nil {
83 | panic(err)
84 | }
85 |
86 | ln, err := gmtls.Listen("tcp", ":443", config)
87 | if err != nil {
88 | panic(err)
89 | }
90 | defer ln.Close()
91 |
92 | http.HandleFunc("/", func(writer http.ResponseWriter, request *http.Request) {
93 | fmt.Fprintf(writer, "hello\n")
94 | })
95 | err = http.Serve(ln, nil)
96 | if err != nil {
97 | panic(err)
98 | }
99 | }
100 | ```
101 |
102 |
103 | 详细服务端的配置流程如下:
104 |
105 | 1. 准备:
106 | - SM2签名密钥对、证书:`sigCert`
107 | - SM2加密密钥对、证书:`encCert`
108 | - RSA/ECC加密密钥对、证书:`rsaKeypair`
109 | 2. 创建一个实现`gmtls.Config#GetCertificate`方法签名的方法,方法需要根据支持的签名类型:
110 | - 含有GMSSL版本:返回SM2签名证书密钥对(`sigCert`)。
111 | - 不含有GMSSL版本:返回RSA签名证书密钥对(`rsaKeypair`)。
112 | 3. 创建一个实现`gmtls.Config#GetKECertificate`方法签名的方法,固定返回SM2加密证书密钥对(`encCert`)。
113 | 4. 创建`GMSupport`并启用,自动切换模式。
114 | 5. 创建`gmtls.Config`对象,接下就可以启动服务端实现自动切换功能。
115 |
116 | ```go
117 | fncGetSignCertKeypair := func(info *gmtls.ClientHelloInfo) (*gmtls.Certificate, error) {
118 | gmFlag := false
119 | // 检查支持协议中是否包含GMSSL
120 | for _, v := range info.SupportedVersions {
121 | if v == gmtls.VersionGMSSL {
122 | gmFlag = true
123 | break
124 | }
125 | }
126 | if gmFlag {
127 | return &sigCert, nil
128 | } else {
129 | return &rsaKeypair, nil
130 | }
131 | }
132 |
133 | fncGetEncCertKeypair := func(info *gmtls.ClientHelloInfo) (*gmtls.Certificate, error) {
134 | return &encCert, nil
135 | }
136 | support := gmtls.NewGMSupport()
137 | support.EnableMixMode()
138 | config := &gmtls.Config{
139 | GMSupport: support,
140 | GetCertificate: fncGetSignCertKeypair,
141 | GetKECertificate: fncGetEncCertKeypair,
142 | }
143 | ```
144 |
145 | > 更多细节请参考: [HTTP over GMTLS/TLS Server Demo](./websvr.go)
146 |
147 |
148 | ## TCLP 双向身份认证
149 |
150 | ### 服务端配置
151 |
152 | 1. 设置启用国密TLCP支持。
153 | 2. 配置服务端签名证书密钥和加密证书密钥。
154 | 3. 设置服务端开启双向身份认证,并要求验证客户端证书。
155 | 4. 配置根证书链,用于验证客户端证书。
156 |
157 | ```go
158 | config := &gmtls.Config{
159 | GMSupport: gmtls.NewGMSupport(),
160 | Certificates: []gmtls.Certificate{sigCert, encCert},
161 | ClientAuth: gmtls.RequireAndVerifyClientCert,
162 | ClientCAs: certPool,
163 | }
164 | ```
165 |
166 | > 更多细节请参考:
167 | >
168 | > - [TLCP服务端 双向身份认证配置 Demo websvr.go #loadServerMutualTLCPAuthConfig](./websvr.go)
169 |
170 |
171 | ### 客户端配置
172 |
173 | 1. 设置启用国密TLCP支持。
174 | 2. 配置双向身份认证的客户端方的签名证书和密钥对。
175 | 3. 提供验证服务端证书的根证书链。
176 | 4. 设置需要进行安全校验。
177 |
178 | 例如:
179 |
180 | ```go
181 | config := &gmtls.Config{
182 | GMSupport: gmtls.NewGMSupport(),
183 | RootCAs: certPool,
184 | Certificates: []gmtls.Certificate{authKeypair},
185 | InsecureSkipVerify: false,
186 | }
187 | ```
188 |
189 | > 更多细节请参考:
190 | >
191 | > - [TLCP客户端 双向身份认证配置 Demo websvr.go #bothAuthConfig](./websvr.go)
192 |
193 |
194 | ## 国密HTTPS客户端
195 |
196 | 为了简化HTTPS客户端的构造`gmtls`包提供下面构造方法:
197 |
198 | - 创建单向身份认证HTTPS客户端:`gmtls.NewHTTPSClient(*x509.CertPool)`
199 | - 创建双向身份认证HTTPS客户端:`gmtls.NewAuthHTTPSClient(*x509.CertPool, *gmtls.Certificate)`
200 | - 创建定制化的TLS连接的HTTPS客户端:`gmtls.NewCustomHTTPSClient(*gmtls.Config)`
201 |
202 | ### HTTPS 单向身份认证
203 |
204 | 单向身份认证客户端,只只验证服务器证书有效性,服务端不对客户端进行身份认证。
205 |
206 | 该模式下进行国密HTTPS的调用你需要:
207 |
208 | 1. 提供根证书链。
209 | 2. 构造HTTP客户端。
210 | 3. 调用API访问HTTPS。
211 |
212 | ```go
213 | package main
214 |
215 | import (
216 | "github.com/tjfoc/gmsm/gmtls"
217 | "github.com/tjfoc/gmsm/x509"
218 | "io/ioutil"
219 | )
220 |
221 | func main() {
222 | // 1. 提供根证书链
223 | certPool := x509.NewCertPool()
224 | cacert, err := ioutil.ReadFile("websvr/certs/SM2_CA.cer")
225 | if err != nil {
226 | panic(err)
227 | }
228 | certPool.AppendCertsFromPEM(cacert)
229 | // 2. 构造HTTP客户端
230 | httpClient := gmtls.NewHTTPSClient(certPool)
231 | // 3. 调用API访问HTTPS
232 | response, err := httpClient.Get("https://localhost:443")
233 | if err != nil {
234 | panic(err)
235 | }
236 | defer response.Body.Close()
237 | // 使用 response 做你需要的事情...
238 | }
239 | ```
240 |
241 | 更多细节见 [gmsm/http_client_test.go#TestNewHTTPSClient2](../http_client_test.go)
242 |
243 | ### HTTPS 双向身份认证
244 |
245 | 双向身份认证,在服务端开启了对客户端的身份认证情况下,国密SSL通行就需要进行双向身份认证。
246 |
247 | 该模式下进行国密HTTPS的调用你需要:
248 |
249 | 1. 提供根证书链。
250 | 2. 提供客户端认证证书、密钥对。
251 | 3. 构造HTTP客户端。
252 | 4. 调用API访问HTTPS。
253 |
254 | ```go
255 | package main
256 |
257 | import (
258 | "github.com/tjfoc/gmsm/gmtls"
259 | "github.com/tjfoc/gmsm/x509"
260 | "io/ioutil"
261 | )
262 |
263 | func main() {
264 | // 1. 提供根证书链
265 | certPool := x509.NewCertPool()
266 | cacert, err := ioutil.ReadFile("websvr/certs/SM2_CA.cer")
267 | if err != nil {
268 | panic(err)
269 | }
270 | certPool.AppendCertsFromPEM(cacert)
271 | // 2. 提供客户端认证证书、密钥对。
272 | clientAuthCert, err := gmtls.LoadX509KeyPair("websvr/certs/sm2_auth_cert.cer", "websvr/certs/sm2_auth_key.pem")
273 | // 3. 构造HTTP客户端。
274 | httpClient := gmtls.NewAuthHTTPSClient(certPool, &clientAuthCert)
275 | // 4. 调用API访问HTTPS。
276 | response, err := httpClient.Get("https://localhost:443")
277 | if err != nil {
278 | panic(err)
279 | }
280 | defer response.Body.Close()
281 | // 使用 response 做你需要的事情...
282 | }
283 | ```
284 |
285 | 更多细节见 [gmsm/http_client_test.go#TestSimpleNewAuthHTTPSClient](../http_client_test.go)
286 |
287 | ## TLCP GCM模式
288 |
289 | 《GBT 38636-2020 信息安全技术 传输层密码协议(TLCP)》协议中增加了GCM可鉴别加密模式相关的系列密码套件。
290 |
291 | 以`ECC_SM4_GCM_SM3` 密码套件为例,该套件使用SM4算法GCM可鉴别加密模式,替换了“SM4 CBC模式 + SM3 HMAC”,其余保持不变。
292 |
293 | GCM模式下:
294 |
295 | - 密文数据结构和生成规则详见: 《GBT 38636-2020》 6.3.3.4.4 认证加密算法的数据处理
296 | - 实现随机数实现细节见:RFC 5116 (AES_GCM 参考 RFC 5288)
297 |
298 |
299 | 如何使用?
300 |
301 | - 目前客户端和服务端均支持 `ECC_SM4_GCM_SM3` 与 `ECC_SM4_CBC_SM3` 密码套件。
302 | - 服务端:无需而外配置。
303 | - 客户端:目前客户单默认使用`ECC_SM4_CBC_SM3`密码套件,需要手动配置才可以使用 `ECC_SM4_GCM_SM3`套件。
304 |
305 | 目前支持TLCP密码套件:
306 |
307 | - `ECC_SM4_GCM_SM3`
308 | - `ECC_SM4_CBC_SM3`
309 | - `ECDHE_SM4_CBC_SM3`
310 | - `ECDHE_SM4_GCM_SM3`
311 |
312 | ### 客户端 GCM配置
313 |
314 | 以单向身份认证举例,只需要在连接配置中增加响应的算法,将GCM模式套件放在数组较前面的位置就可以。
315 |
316 | 示例如下:
317 |
318 | ```go
319 | package main
320 |
321 | import (
322 | "github.com/tjfoc/gmsm/gmtls"
323 | "github.com/tjfoc/gmsm/x509"
324 | "io/ioutil"
325 | "log"
326 | )
327 |
328 | func main() {
329 | // 信任的根证书
330 | certPool := x509.NewCertPool()
331 | cacert, err := ioutil.ReadFile("root.cer")
332 | if err != nil {
333 | log.Fatal(err)
334 | }
335 | certPool.AppendCertsFromPEM(cacert)
336 | cert, err := gmtls.LoadX509KeyPair("sm2_cli.cer", "sm2_cli.pem")
337 |
338 | config := &gmtls.Config{
339 | GMSupport: &gmtls.GMSupport{},
340 | RootCAs: certPool,
341 | Certificates: []gmtls.Certificate{cert},
342 | // 设置GCM模式套件放在前面
343 | CipherSuites: []uint16{gmtls.GMTLS_ECC_SM4_GCM_SM3, gmtls.GMTLS_ECC_SM4_CBC_SM3},
344 | }
345 |
346 | conn, err := gmtls.Dial("tcp", "localhost:50052", config)
347 | if err != nil {
348 | panic(err)
349 | }
350 | defer conn.Close()
351 |
352 | // 对 conn 读取或写入
353 | }
354 | ```
355 |
356 | ### 关于 TLCP AEAD随机数
357 |
358 | 该套件采用 显式 和 隐式 随机数构造,AEAD随机数(Nonce),总长12字节,4字节隐式随机数、8字节显式部分。
359 |
360 | ```txt
361 | +---------------------+----------------------------------+
362 | | Fixed(4byte) | Counter(8byte) |
363 | +---------------------+----------------------------------+
364 | <---- 隐式随机数 ---> <------------ 显式部分 ------------>
365 | ```
366 |
367 | - 隐式随机数为: 工作密钥中的 客户端写IV(`client_write_IV `) 或 服务端写IV(`server_write_IV`)。
368 | - 显式部分为: 数据包序号(`seq_num`),也就是`GenericAEADCipher.nonce_explicit`字段。
369 |
370 | > 详见 RFC 5116 3.2. Recommended Nonce Formation
371 |
372 | AEAD SM4 与 AEAD AES 128 实现一致。
373 |
374 |
--------------------------------------------------------------------------------