Skip to content

Commit

Permalink
优化 PKCS8 加密解密
Browse files Browse the repository at this point in the history
  • Loading branch information
deatil committed Dec 30, 2024
1 parent dec306a commit e4a430e
Show file tree
Hide file tree
Showing 6 changed files with 218 additions and 22 deletions.
1 change: 1 addition & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
* dh 使用文档: [dh.md](dh.md)
* ca 使用文档: [ca.md](ca.md)
* pkcs7 使用文档: [pkcs7.md](pkcs7.md)
* pkcs8 使用文档: [pkcs8.md](pkcs8.md)
* pkcs12 使用文档: [pkcs12.md](pkcs12.md)
* ssh 使用文档: [ssh.md](ssh.md)
* jceks/jks 使用文档: [jceks.md](jceks.md)
Expand Down
87 changes: 87 additions & 0 deletions docs/pkcs8.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
### PKCS8 使用文档


#### 包引入 / import pkcs8
~~~go
import (
"github.com/deatil/go-cryptobin/pkcs8"
)
~~~


#### 加密证书 / Encrypt key

~~~go
import (
"crypto/rand"

"github.com/deatil/go-cryptobin/pkcs8"
)

func main() {
var data []byte = []byte("...")
var pass []byte = []byte("...")

var opts = pkcs8.DefaultOpts

// 可用默认设置: [DefaultPBKDF2Opts | DefaultSMPBKDF2Opts | DefaultScryptOpts | DefaultOpts | DefaultSMOpts]
block, err := EncryptPEMBlock(rand.Reader, "ENCRYPTED PRIVATE KEY", data, pass, opts)

// 自定义设置
var opts1 = pkcs8.Opts{
Cipher: pkcs8.SM4CFB,
KDFOpts: pkcs8.SMPBKDF2Opts{
SaltSize: 8,
IterationCount: 5000,
HMACHash: pkcs8.DefaultSMHash,
},
}
var opts2 = pkcs8.PBKDF2Opts{
SaltSize: 16,
IterationCount: 10000,
}
var opts3 = pkcs8.SMPBKDF2Opts{
SaltSize: 16,
IterationCount: 10000,
HMACHash: DefaultSMHash,
}
var opts4 = pkcs8.ScryptOpts{
SaltSize: 16,
CostParameter: 1 << 2,
BlockSize: 8,
ParallelizationParameter: 1,
}
var opts5 = pkcs8.Opts{
Cipher: pkcs8.AES256CBC,
KDFOpts: pkcs8.DefaultPBKDF2Opts,
}

// 使用铺助函数生成设置
opts, err := pkcs8.MakeOpts("AES256CBC", "SHA256")
opts, err := pkcs8.MakeOpts(pkcs8.AES256CBC, SHA256)
opts, err := pkcs8.MakeOpts(pkcs8.SHA1AndDES)

}
~~~


#### 解密加密证书 / Decrypt key

~~~go
import (
"encoding/pem"

"github.com/deatil/go-cryptobin/pkcs8"
)

func main() {
var pemkey []byte = []byte("...")
var password []byte = []byte("...")

block, _ := pem.Decode(pemkey)

dekey, err := DecryptPEMBlock(block, password)
if err != nil {
// return error
}
}
16 changes: 8 additions & 8 deletions pkcs8/pbes1/pkcs8.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@ type encryptedPrivateKeyInfo struct {

// 加密 PKCS8 私钥
func EncryptPKCS8PrivateKey(
rand io.Reader,
rand io.Reader,
blockType string,
data []byte,
password []byte,
cipher Cipher,
data []byte,
password []byte,
cipher Cipher,
) (*pem.Block, error) {
if cipher == nil {
return nil, errors.New("failed to encrypt PEM: unknown cipher")
Expand Down Expand Up @@ -100,11 +100,11 @@ func DecryptPKCS8PrivateKey(data, password []byte) ([]byte, error) {

// 加密 PKCS8 私钥,不处理密码
func EncryptPKCS8Privatekey(
rand io.Reader,
rand io.Reader,
blockType string,
data []byte,
password []byte,
cipher Cipher,
data []byte,
password []byte,
cipher Cipher,
) (*pem.Block, error) {
if cipher == nil {
return nil, errors.New("failed to encrypt PEM: unknown cipher")
Expand Down
38 changes: 28 additions & 10 deletions pkcs8/pbes2/helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ func GetHashFromName(name string) Hash {
return HashMap["SHA1"]
}

// 解析配置
func ParseOpts(opts ...any) (Opts, error) {
// 生成设置
func MakeOpts(opts ...any) (Opts, error) {
if len(opts) == 0 {
return DefaultOpts, nil
}
Expand All @@ -41,20 +41,30 @@ func ParseOpts(opts ...any) (Opts, error) {
IterationCount: 10000,
}

// 设置
// hash
if len(opts) > 1 {
switch hash := opts[1].(type) {
case Hash:
kdfOpts.HMACHash = hash
case string:
kdfOpts.HMACHash = GetHashFromName(hash)
}
}

// Opts
newOpts := Opts{
Cipher: cipher,
KDFOpts: kdfOpts,
}

return newOpts, nil
case string:
opt := "AES256CBC"
cipName := "AES256CBC"
if len(opts) > 0 {
opt = opts[0].(string)
cipName = opts[0].(string)
}

cipher := GetCipherFromName(opt)
cipher := GetCipherFromName(cipName)

kdfOpts := PBKDF2Opts{
SaltSize: 16,
Expand All @@ -63,12 +73,15 @@ func ParseOpts(opts ...any) (Opts, error) {

// hash
if len(opts) > 1 {
hash := opts[1].(string)

kdfOpts.HMACHash = GetHashFromName(hash)
switch hash := opts[1].(type) {
case Hash:
kdfOpts.HMACHash = hash
case string:
kdfOpts.HMACHash = GetHashFromName(hash)
}
}

// 设置
// Opts
newOpts := Opts{
Cipher: cipher,
KDFOpts: kdfOpts,
Expand All @@ -79,3 +92,8 @@ func ParseOpts(opts ...any) (Opts, error) {

return DefaultOpts, nil
}

// 解析生成设置
func ParseOpts(opts ...any) (Opts, error) {
return MakeOpts(opts...)
}
85 changes: 85 additions & 0 deletions pkcs8/pbes2/pkcs8_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,88 @@ func Test_prfByOID_fail(t *testing.T) {
check := "go-cryptobin/pkcs8: unsupported hash (OID: 1.222.643.777.12.13.5.1)"
assertEqual(err.Error(), check, "Test_prfByOID_fail")
}

func Test_EncryptPKCS8PrivateKey2(t *testing.T) {
test_EncryptPKCS8PrivateKey2(t, "test 1", DefaultOpts)
test_EncryptPKCS8PrivateKey2(t, "test 2", DefaultSMOpts)

test_EncryptPKCS8PrivateKey2(t, "test 3", Opts{
Cipher: AES256CBC,
KDFOpts: DefaultPBKDF2Opts,
})
test_EncryptPKCS8PrivateKey2(t, "test 4", Opts{
Cipher: AES256CBC,
KDFOpts: DefaultSMPBKDF2Opts,
})
test_EncryptPKCS8PrivateKey2(t, "test 5", Opts{
Cipher: AES256CBC,
KDFOpts: DefaultScryptOpts,
})

test_EncryptPKCS8PrivateKey2(t, "test 6", Opts{
Cipher: AES256CBC,
KDFOpts: PBKDF2Opts{
SaltSize: 16,
IterationCount: 10000,
},
})
test_EncryptPKCS8PrivateKey2(t, "test 7", Opts{
Cipher: AES256CBC,
KDFOpts: PBKDF2Opts{
SaltSize: 16,
IterationCount: 10000,
HMACHash: SHA256,
},
})

opts21, _ := MakeOpts(Opts{
Cipher: AES256CBC,
KDFOpts: PBKDF2Opts{
SaltSize: 16,
IterationCount: 10000,
HMACHash: SHA256,
},
})
test_EncryptPKCS8PrivateKey2(t, "test 8", opts21)

opts22, _ := MakeOpts(AES256CBC)
test_EncryptPKCS8PrivateKey2(t, "test 9", opts22)

opts23, _ := MakeOpts(AES256CBC, SHA256)
test_EncryptPKCS8PrivateKey2(t, "test 10", opts23)

opts23_1, _ := MakeOpts(AES256CBC, "SHA256")
test_EncryptPKCS8PrivateKey2(t, "test 10-1", opts23_1)

opts24, _ := MakeOpts("AES256CBC")
test_EncryptPKCS8PrivateKey2(t, "test 11", opts24)

opts25, _ := MakeOpts("AES256CBC", "SHA256")
test_EncryptPKCS8PrivateKey2(t, "test 12", opts25)

opts26, _ := MakeOpts("AES256CBC", SHA256)
test_EncryptPKCS8PrivateKey2(t, "test 13", opts26)

}

func test_EncryptPKCS8PrivateKey2(t *testing.T, name string, opts Opts) {
assertEqual := cryptobin_test.AssertEqualT(t)
assertError := cryptobin_test.AssertErrorT(t)
assertNotEmpty := cryptobin_test.AssertNotEmptyT(t)

t.Run(name, func(t *testing.T) {
data := "test-data"
pass := "test-pass"

block, err := EncryptPKCS8PrivateKey(rand.Reader, "ENCRYPTED PRIVATE KEY", []byte(data), []byte(pass), opts)
assertError(err, "test_EncryptPKCS8PrivateKey2-EN")
assertNotEmpty(block.Bytes, "test_EncryptPKCS8PrivateKey2-EN")

deData, err := DecryptPKCS8PrivateKey(block.Bytes, []byte(pass))
assertError(err, "test_EncryptPKCS8PrivateKey2-DE")
assertNotEmpty(deData, "test_EncryptPKCS8PrivateKey2-DE")

assertEqual(string(deData), data, "test_EncryptPKCS8PrivateKey2")
})

}
13 changes: 9 additions & 4 deletions pkcs8/pkcs8.go
Original file line number Diff line number Diff line change
Expand Up @@ -171,10 +171,10 @@ var (
DefaultSMOpts = pbes2.DefaultSMOpts
)

// 解析设置
// opt, err := ParseOpts("AES256CBC", "SHA256")
// 生成设置
// opt, err := MakeOpts("AES256CBC", "SHA256")
// block, err := EncryptPEMBlock(rand.Reader, "ENCRYPTED PRIVATE KEY", data, password, opt)
func ParseOpts(opts ...any) (any, error) {
func MakeOpts(opts ...any) (any, error) {
var opt any
var err error

Expand All @@ -187,7 +187,7 @@ func ParseOpts(opts ...any) (any, error) {
}

if opt == nil {
opt, err = pbes2.ParseOpts(opts...)
opt, err = pbes2.MakeOpts(opts...)
if err != nil {
return nil, err
}
Expand All @@ -196,6 +196,11 @@ func ParseOpts(opts ...any) (any, error) {
return opt, nil
}

// 解析生成设置
func ParseOpts(opts ...any) (any, error) {
return MakeOpts(opts...)
}

// 加密
// block, err := EncryptPEMBlock(rand.Reader, "ENCRYPTED PRIVATE KEY", data, password, DESCBC)
// block, err := EncryptPEMBlock(rand.Reader, "ENCRYPTED PRIVATE KEY", data, password, DefaultOpts)
Expand Down

0 comments on commit e4a430e

Please sign in to comment.