Documentation ¶
Overview ¶
Package pkcs8 implements functions to parse and convert private keys in PKCS#8 format with ShangMi(SM) support, as defined in RFC5208 and RFC5958.
Index ¶
- Variables
- func ConvertPrivateKeyToPKCS8(priv any, v ...[]byte) ([]byte, error)
- func MarshalPrivateKey(priv any, password []byte, opts *Opts) ([]byte, error)
- func ParsePKCS8PrivateKey(der []byte, v ...[]byte) (any, error)
- func ParsePKCS8PrivateKeyECDSA(der []byte, v ...[]byte) (*ecdsa.PrivateKey, error)
- func ParsePKCS8PrivateKeyRSA(der []byte, v ...[]byte) (*rsa.PrivateKey, error)
- func ParsePKCS8PrivateKeySM2(der []byte, v ...[]byte) (*sm2.PrivateKey, error)
- func ParseSM9EncryptMasterPrivateKey(der []byte, v ...[]byte) (*sm9.EncryptMasterPrivateKey, error)
- func ParseSM9EncryptPrivateKey(der []byte, v ...[]byte) (*sm9.EncryptPrivateKey, error)
- func ParseSM9SignMasterPrivateKey(der []byte, v ...[]byte) (*sm9.SignMasterPrivateKey, error)
- func ParseSM9SignPrivateKey(der []byte, v ...[]byte) (*sm9.SignPrivateKey, error)
- func RegisterKDF(oid asn1.ObjectIdentifier, params func() KDFParameters)
- type Hash
- type KDFOpts
- type KDFParameters
- type Opts
- type PBKDF2Opts
- type ScryptOpts
Examples ¶
- MarshalPrivateKey
- MarshalPrivateKey (WithoutPassword)
- MarshalPrivateKey (WithoutPasswordSM9MasterSignKey)
- ParsePKCS8PrivateKey
- ParsePKCS8PrivateKey (WithoutPassword)
- ParsePKCS8PrivateKeySM2
- ParsePKCS8PrivateKeySM2 (WithoutPassword)
- ParsePrivateKey
- ParsePrivateKey (WithoutPassword)
- ParseSM9SignMasterPrivateKey (WithoutPassword)
Constants ¶
This section is empty.
Variables ¶
var DefaultOpts = &Opts{ Cipher: pkcs.AES256CBC, KDFOpts: PBKDF2Opts{ SaltSize: 8, IterationCount: 10000, HMACHash: SHA256, }, }
DefaultOpts are the default options for encrypting a key if none are given. The defaults can be changed by the library user.
Functions ¶
func ConvertPrivateKeyToPKCS8 ¶
ConvertPrivateKeyToPKCS8 converts the private key into PKCS#8 format. To encrypt the private key, the password of []byte type should be provided as the second parameter.
func MarshalPrivateKey ¶
MarshalPrivateKey encodes a private key into DER-encoded PKCS#8 with the given options. Password can be nil.
Example ¶
package main import ( "encoding/hex" "encoding/pem" "fmt" "math/big" "os" "github.com/emmansun/gmsm/pkcs" "github.com/emmansun/gmsm/pkcs8" "github.com/emmansun/gmsm/sm2" ) func main() { // real private key should be from secret storage, or generate directly privKey, _ := hex.DecodeString("6c5a0a0b2eed3cbec3e4f1252bfe0e28c504a1c6bf1999eebb0af9ef0f8e6c85") d := new(big.Int).SetBytes(privKey) testkey := new(sm2.PrivateKey) testkey.Curve = sm2.P256() testkey.D = d testkey.PublicKey.X, testkey.PublicKey.Y = testkey.ScalarBaseMult(testkey.D.Bytes()) password := []byte("Password1") opts := &pkcs8.Opts{ Cipher: pkcs.SM4CBC, KDFOpts: pkcs8.PBKDF2Opts{ SaltSize: 16, IterationCount: 16, HMACHash: pkcs8.SM3, }, } // generate der bytes der, err := pkcs8.MarshalPrivateKey(testkey, password, opts) if err != nil { fmt.Fprintf(os.Stderr, "Error from MarshalPrivateKey: %s\n", err) return } // encode der bytes to pem block := &pem.Block{Bytes: der, Type: "ENCRYPTED PRIVATE KEY"} pemContent := string(pem.EncodeToMemory(block)) fmt.Printf("%v\n", pemContent) }
Output:
Example (WithoutPassword) ¶
package main import ( "encoding/hex" "encoding/pem" "fmt" "math/big" "os" "github.com/emmansun/gmsm/pkcs8" "github.com/emmansun/gmsm/sm2" ) func main() { // real private key should be from secret storage, or generate directly privKey, _ := hex.DecodeString("6c5a0a0b2eed3cbec3e4f1252bfe0e28c504a1c6bf1999eebb0af9ef0f8e6c85") d := new(big.Int).SetBytes(privKey) testkey := new(sm2.PrivateKey) testkey.Curve = sm2.P256() testkey.D = d testkey.PublicKey.X, testkey.PublicKey.Y = testkey.ScalarBaseMult(testkey.D.Bytes()) // generate der bytes der, err := pkcs8.MarshalPrivateKey(testkey, nil, nil) if err != nil { fmt.Fprintf(os.Stderr, "Error from MarshalPrivateKey: %s\n", err) return } // encode der bytes to pem block := &pem.Block{Bytes: der, Type: "PRIVATE KEY"} pemContent := string(pem.EncodeToMemory(block)) fmt.Printf("%v\n", pemContent) }
Output:
Example (WithoutPasswordSM9MasterSignKey) ¶
package main import ( "encoding/hex" "encoding/pem" "fmt" "math/big" "os" "github.com/emmansun/gmsm/pkcs8" "github.com/emmansun/gmsm/sm9" "golang.org/x/crypto/cryptobyte" ) func main() { // real private key should be from secret storage, or generate directly kb, _ := hex.DecodeString("0130E78459D78545CB54C587E02CF480CE0B66340F319F348A1D5B1F2DC5F4") var b cryptobyte.Builder b.AddASN1BigInt(new(big.Int).SetBytes(kb)) kb, _ = b.Bytes() testkey := new(sm9.SignMasterPrivateKey) err := testkey.UnmarshalASN1(kb) if err != nil { panic(err) } // generate der bytes der, err := pkcs8.MarshalPrivateKey(testkey, nil, nil) if err != nil { fmt.Fprintf(os.Stderr, "Error from MarshalPrivateKey: %s\n", err) return } // encode der bytes to pem block := &pem.Block{Bytes: der, Type: "SM9 SIGN PRIVATE KEY"} pemContent := string(pem.EncodeToMemory(block)) fmt.Printf("%v\n", pemContent) }
Output:
func ParsePKCS8PrivateKey ¶
ParsePKCS8PrivateKey parses encrypted/unencrypted private keys in PKCS#8 format. To parse encrypted private keys, a password of []byte type should be provided to the function as the second parameter.
Example ¶
package main import ( "encoding/pem" "fmt" "os" "github.com/emmansun/gmsm/pkcs8" ) func main() { const privateKeyPem = ` -----BEGIN ENCRYPTED PRIVATE KEY----- MIH2MGEGCSqGSIb3DQEFDTBUMDQGCSqGSIb3DQEFDDAnBBDa6ckWJNP3QBD7MIF8 4nVqAgEQAgEQMA0GCSqBHM9VAYMRAgUAMBwGCCqBHM9VAWgCBBDMUgr+5Y/XN2g9 mPGiISzGBIGQytwK98/ET4WrS0H7AsUri6FTqztrzAvgzFl3+s9AsaYtUlzE3EzE x6RWxo8kpKO2yj0a/Jh9WZCD4XAcoZ9aMopiWlOdpXJr/iQlMGdirCYIoF37lHMc jZHNffmk4ii7NxCfjrzpiFq4clYsNMXeSEnq1tuOEur4kYcjHYSIFc9bPG656a60 +SIJsJuPFi0f -----END ENCRYPTED PRIVATE KEY-----` password := []byte("Password1") block, _ := pem.Decode([]byte(privateKeyPem)) if block == nil { fmt.Fprintf(os.Stderr, "Failed to parse PEM block\n") return } pk, err := pkcs8.ParsePKCS8PrivateKey(block.Bytes, password) if err != nil { fmt.Fprintf(os.Stderr, "Error from ParsePKCS8PrivateKey: %s\n", err) return } if pk != nil { fmt.Println("ok") } else { fmt.Println("fail") } }
Output: ok
Example (WithoutPassword) ¶
package main import ( "encoding/pem" "fmt" "os" "github.com/emmansun/gmsm/pkcs8" ) func main() { const privateKeyPem = ` -----BEGIN PRIVATE KEY----- MIGHAgEAMBMGByqGSM49AgEGCCqBHM9VAYItBG0wawIBAQQgbFoKCy7tPL7D5PEl K/4OKMUEoca/GZnuuwr57w+ObIWhRANCAASDVuZCpA69GNKbo1MvvZ87vujwJ8P2 85pbovhwNp+ZiJgfXv5V0cXN9sDvKwcIR6FPf99CcqjfCcRC8wWK+Uuh -----END PRIVATE KEY-----` block, _ := pem.Decode([]byte(privateKeyPem)) if block == nil { fmt.Fprintf(os.Stderr, "Failed to parse PEM block\n") return } pk, err := pkcs8.ParsePKCS8PrivateKey(block.Bytes) if err != nil { fmt.Fprintf(os.Stderr, "Error from ParsePKCS8PrivateKey: %s\n", err) return } if pk != nil { fmt.Println("ok") } else { fmt.Println("fail") } }
Output: ok
func ParsePKCS8PrivateKeyECDSA ¶
func ParsePKCS8PrivateKeyECDSA(der []byte, v ...[]byte) (*ecdsa.PrivateKey, error)
ParsePKCS8PrivateKeyECDSA parses encrypted/unencrypted private keys in PKCS#8 format. To parse encrypted private keys, a password of []byte type should be provided to the function as the second parameter.
func ParsePKCS8PrivateKeyRSA ¶
func ParsePKCS8PrivateKeyRSA(der []byte, v ...[]byte) (*rsa.PrivateKey, error)
ParsePKCS8PrivateKeyRSA parses encrypted/unencrypted private keys in PKCS#8 format. To parse encrypted private keys, a password of []byte type should be provided to the function as the second parameter.
func ParsePKCS8PrivateKeySM2 ¶
func ParsePKCS8PrivateKeySM2(der []byte, v ...[]byte) (*sm2.PrivateKey, error)
ParsePKCS8PrivateKeySM2 parses encrypted/unencrypted SM2 private key in PKCS#8 format. To parse encrypted private keys, a password of []byte type should be provided to the function as the second parameter.
Example ¶
package main import ( "encoding/pem" "fmt" "os" "github.com/emmansun/gmsm/pkcs8" ) func main() { const privateKeyPem = ` -----BEGIN ENCRYPTED PRIVATE KEY----- MIH2MGEGCSqGSIb3DQEFDTBUMDQGCSqGSIb3DQEFDDAnBBDa6ckWJNP3QBD7MIF8 4nVqAgEQAgEQMA0GCSqBHM9VAYMRAgUAMBwGCCqBHM9VAWgCBBDMUgr+5Y/XN2g9 mPGiISzGBIGQytwK98/ET4WrS0H7AsUri6FTqztrzAvgzFl3+s9AsaYtUlzE3EzE x6RWxo8kpKO2yj0a/Jh9WZCD4XAcoZ9aMopiWlOdpXJr/iQlMGdirCYIoF37lHMc jZHNffmk4ii7NxCfjrzpiFq4clYsNMXeSEnq1tuOEur4kYcjHYSIFc9bPG656a60 +SIJsJuPFi0f -----END ENCRYPTED PRIVATE KEY-----` password := []byte("Password1") block, _ := pem.Decode([]byte(privateKeyPem)) if block == nil { fmt.Fprintf(os.Stderr, "Failed to parse PEM block\n") return } pk, err := pkcs8.ParsePKCS8PrivateKeySM2(block.Bytes, password) if err != nil { fmt.Fprintf(os.Stderr, "Error from ParsePKCS8PrivateKeySM2: %s\n", err) return } if pk != nil { fmt.Println("ok") } else { fmt.Println("fail") } }
Output: ok
Example (WithoutPassword) ¶
package main import ( "encoding/pem" "fmt" "os" "github.com/emmansun/gmsm/pkcs8" ) func main() { const privateKeyPem = ` -----BEGIN PRIVATE KEY----- MIGHAgEAMBMGByqGSM49AgEGCCqBHM9VAYItBG0wawIBAQQgbFoKCy7tPL7D5PEl K/4OKMUEoca/GZnuuwr57w+ObIWhRANCAASDVuZCpA69GNKbo1MvvZ87vujwJ8P2 85pbovhwNp+ZiJgfXv5V0cXN9sDvKwcIR6FPf99CcqjfCcRC8wWK+Uuh -----END PRIVATE KEY-----` block, _ := pem.Decode([]byte(privateKeyPem)) if block == nil { fmt.Fprintf(os.Stderr, "Failed to parse PEM block\n") return } pk, err := pkcs8.ParsePKCS8PrivateKeySM2(block.Bytes) if err != nil { fmt.Fprintf(os.Stderr, "Error from ParsePKCS8PrivateKeySM2: %s\n", err) return } if pk != nil { fmt.Println("ok") } else { fmt.Println("fail") } }
Output: ok
func ParseSM9EncryptMasterPrivateKey ¶ added in v0.15.0
func ParseSM9EncryptMasterPrivateKey(der []byte, v ...[]byte) (*sm9.EncryptMasterPrivateKey, error)
ParseSM9EncryptMasterPrivateKey parses encrypted/unencrypted SM9 encrypt master private key in PKCS#8 format. To parse encrypted private keys, a password of []byte type should be provided to the function as the second parameter.
func ParseSM9EncryptPrivateKey ¶ added in v0.15.0
func ParseSM9EncryptPrivateKey(der []byte, v ...[]byte) (*sm9.EncryptPrivateKey, error)
ParseSM9EncryptPrivateKey parses encrypted/unencrypted SM9 encrypt private key in PKCS#8 format. To parse encrypted private keys, a password of []byte type should be provided to the function as the second parameter.
func ParseSM9SignMasterPrivateKey ¶ added in v0.15.0
func ParseSM9SignMasterPrivateKey(der []byte, v ...[]byte) (*sm9.SignMasterPrivateKey, error)
ParseSM9SignMasterPrivateKey parses encrypted/unencrypted SM9 sign master private key in PKCS#8 format. To parse encrypted private keys, a password of []byte type should be provided to the function as the second parameter.
Example (WithoutPassword) ¶
package main import ( "encoding/pem" "fmt" "os" "github.com/emmansun/gmsm/pkcs8" ) func main() { const privateKeyPem = ` -----BEGIN SM9 SIGN PRIVATE KEY----- MIHGAgEAMBUGCCqBHM9VAYIuBgkqgRzPVQGCLgEEgakwgaYCHwEw54RZ14VFy1TF h+As9IDOC2Y0DzGfNIodWx8txfQDgYIABJ9kCAswhPcz5Ir/S0G1ZQEc4HEcXjks +wqxtnkblMQIKduhFhUtH3hs6EPtJKO1c0FNIXc4apLdjxTWVpbqXjJphQk4q+oB ErVzKfRH46DLrT4v2xp38zXonhQI0O8cJUHgClPdpTLaGnzgJ7ekb3QQBuhfXN/w cw51wF+04yFt -----END SM9 SIGN PRIVATE KEY-----` block, _ := pem.Decode([]byte(privateKeyPem)) if block == nil { fmt.Fprintf(os.Stderr, "Failed to parse PEM block\n") return } pk, err := pkcs8.ParseSM9SignMasterPrivateKey(block.Bytes) if err != nil { fmt.Fprintf(os.Stderr, "Error from ParseSM9SignMasterPrivateKey: %s\n", err) return } if pk != nil { fmt.Println("ok") } else { fmt.Println("fail") } }
Output: ok
func ParseSM9SignPrivateKey ¶ added in v0.15.0
func ParseSM9SignPrivateKey(der []byte, v ...[]byte) (*sm9.SignPrivateKey, error)
ParseSM9SignPrivateKey parses encrypted/unencrypted SM9 sign private key in PKCS#8 format. To parse encrypted private keys, a password of []byte type should be provided to the function as the second parameter.
func RegisterKDF ¶
func RegisterKDF(oid asn1.ObjectIdentifier, params func() KDFParameters)
RegisterKDF registers a function that returns a new instance of the given KDF parameters. This allows the library to support client-provided KDFs.
Types ¶
type Hash ¶
type Hash uint
Hash identifies a cryptographic hash function that is implemented in another package.
type KDFOpts ¶
type KDFOpts interface { // DeriveKey derives a key of size bytes from the given password and salt. // It returns the key and the ASN.1-encodable parameters used. DeriveKey(password, salt []byte, size int) (key []byte, params KDFParameters, err error) // GetSaltSize returns the salt size specified. GetSaltSize() int // OID returns the OID of the KDF specified. OID() asn1.ObjectIdentifier }
KDFOpts contains options for a key derivation function. An implementation of this interface must be specified when encrypting a PKCS#8 key.
type KDFParameters ¶
type KDFParameters interface { // DeriveKey derives a key of size bytes from the given password. // It uses the salt from the decoded parameters. DeriveKey(password []byte, size int) (key []byte, err error) }
KDFParameters contains parameters (salt, etc.) for a key deriviation function. It must be a ASN.1-decodable structure. An implementation of this interface is created when decoding an encrypted PKCS#8 key.
func ParsePrivateKey ¶
func ParsePrivateKey(der []byte, password []byte) (any, KDFParameters, error)
ParsePrivateKey parses a DER-encoded PKCS#8 private key. Password can be nil. This is equivalent to ParsePKCS8PrivateKey.
Example ¶
package main import ( "encoding/pem" "fmt" "os" "github.com/emmansun/gmsm/pkcs8" ) func main() { const privateKeyPem = ` -----BEGIN ENCRYPTED PRIVATE KEY----- MIH2MGEGCSqGSIb3DQEFDTBUMDQGCSqGSIb3DQEFDDAnBBDa6ckWJNP3QBD7MIF8 4nVqAgEQAgEQMA0GCSqBHM9VAYMRAgUAMBwGCCqBHM9VAWgCBBDMUgr+5Y/XN2g9 mPGiISzGBIGQytwK98/ET4WrS0H7AsUri6FTqztrzAvgzFl3+s9AsaYtUlzE3EzE x6RWxo8kpKO2yj0a/Jh9WZCD4XAcoZ9aMopiWlOdpXJr/iQlMGdirCYIoF37lHMc jZHNffmk4ii7NxCfjrzpiFq4clYsNMXeSEnq1tuOEur4kYcjHYSIFc9bPG656a60 +SIJsJuPFi0f -----END ENCRYPTED PRIVATE KEY-----` password := []byte("Password1") block, _ := pem.Decode([]byte(privateKeyPem)) if block == nil { fmt.Fprintf(os.Stderr, "Failed to parse PEM block\n") return } pk, params, err := pkcs8.ParsePrivateKey(block.Bytes, password) if err != nil { fmt.Fprintf(os.Stderr, "Error from ParsePrivateKey: %s\n", err) return } if params != nil && pk != nil { fmt.Println("ok") } else { fmt.Println("fail") } }
Output: ok
Example (WithoutPassword) ¶
package main import ( "encoding/pem" "fmt" "os" "github.com/emmansun/gmsm/pkcs8" ) func main() { const privateKeyPem = ` -----BEGIN PRIVATE KEY----- MIGHAgEAMBMGByqGSM49AgEGCCqBHM9VAYItBG0wawIBAQQgbFoKCy7tPL7D5PEl K/4OKMUEoca/GZnuuwr57w+ObIWhRANCAASDVuZCpA69GNKbo1MvvZ87vujwJ8P2 85pbovhwNp+ZiJgfXv5V0cXN9sDvKwcIR6FPf99CcqjfCcRC8wWK+Uuh -----END PRIVATE KEY-----` block, _ := pem.Decode([]byte(privateKeyPem)) if block == nil { fmt.Fprintf(os.Stderr, "Failed to parse PEM block\n") return } pk, params, err := pkcs8.ParsePrivateKey(block.Bytes, nil) if err != nil { fmt.Fprintf(os.Stderr, "Error from ParsePrivateKey: %s\n", err) return } if params == nil && pk != nil { fmt.Println("ok") } else { fmt.Println("fail") } }
Output: ok
type PBKDF2Opts ¶
PBKDF2Opts contains options for the PBKDF2 key derivation function.
func (PBKDF2Opts) DeriveKey ¶
func (p PBKDF2Opts) DeriveKey(password, salt []byte, size int) ( key []byte, params KDFParameters, err error)
func (PBKDF2Opts) GetSaltSize ¶
func (p PBKDF2Opts) GetSaltSize() int
func (PBKDF2Opts) OID ¶
func (p PBKDF2Opts) OID() asn1.ObjectIdentifier
type ScryptOpts ¶
type ScryptOpts struct { SaltSize int CostParameter int BlockSize int ParallelizationParameter int }
ScryptOpts contains options for the scrypt key derivation function.
func (ScryptOpts) DeriveKey ¶
func (p ScryptOpts) DeriveKey(password, salt []byte, size int) ( key []byte, params KDFParameters, err error)
func (ScryptOpts) GetSaltSize ¶
func (p ScryptOpts) GetSaltSize() int
func (ScryptOpts) OID ¶
func (p ScryptOpts) OID() asn1.ObjectIdentifier