init: v1.0.0
This commit is contained in:
+176
@@ -0,0 +1,176 @@
|
||||
package pbkd
|
||||
|
||||
import (
|
||||
"encoding/asn1"
|
||||
|
||||
"golang.org/x/crypto/cryptobyte"
|
||||
cryptobyte_asn1 "golang.org/x/crypto/cryptobyte/asn1"
|
||||
"xdx.jelly/xgcl/gerrors"
|
||||
)
|
||||
|
||||
// id-PBES2 OBJECT IDENTIFIER ::= {pkcs-5 13}
|
||||
//
|
||||
// The parameters field associated with this OID in an
|
||||
// AlgorithmIdentifier shall have type PBES2-params:
|
||||
//
|
||||
// PBES2-params ::= SEQUENCE {
|
||||
// keyDerivationFunc AlgorithmIdentifier {{PBES2-KDFs}},
|
||||
// encryptionScheme AlgorithmIdentifier {{PBES2-Encs}}
|
||||
// }
|
||||
//
|
||||
// PBKDF2-params ::= SEQUENCE {
|
||||
// salt CHOICE {
|
||||
// specified OCTET STRING,
|
||||
// otherSource AlgorithmIdentifier {{PBKDF2-SaltSources}}
|
||||
// },
|
||||
// iterationCount INTEGER (1..MAX),
|
||||
// keyLength INTEGER (1..MAX) OPTIONAL,
|
||||
// prf AlgorithmIdentifier {{PBKDF2-PRFs}} DEFAULT algid-hmacWithSHA1 }
|
||||
|
||||
var (
|
||||
// oidHmacWithSHA1 = asn1.ObjectIdentifier{1, 2, 156, 10197, 1, 401, 2}
|
||||
IdHmacWithSm3 = asn1.ObjectIdentifier{1, 2, 156, 10197, 1, 401, 2} //SM3密码杂凑算法,有密钥使用
|
||||
IdEncSM4CBC = asn1.ObjectIdentifier{1, 2, 156, 10197, 1, 104, 2} // SM4-CBC
|
||||
|
||||
IdPkcs5PBKDF2 = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 5, 12} // pkcs5PBKDF2 (PKCS #5 v2.0)
|
||||
IdPkcs5PBES2 = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 5, 13} // pkcs5PBES2 (PKCS #5 v2.0)
|
||||
)
|
||||
|
||||
func MarshalASN1PBKDF2(salt []byte, iterationCount int, keyLength int) ([]byte, error) {
|
||||
pbkdf2 := &PBKDF2{
|
||||
ObjectIdentifier: IdPkcs5PBKDF2,
|
||||
}
|
||||
pbkdf2.Param.Salt = salt
|
||||
pbkdf2.Param.IterationCount = iterationCount
|
||||
pbkdf2.Param.KeyLength = new(int)
|
||||
*pbkdf2.Param.KeyLength = keyLength
|
||||
pbkdf2.Param.Prf.ObjectIdentifier = IdHmacWithSm3
|
||||
return pbkdf2.MarshalASN1()
|
||||
}
|
||||
|
||||
type PBKDF2 struct {
|
||||
// Salt only support OCTET STRING
|
||||
asn1.ObjectIdentifier
|
||||
Param struct {
|
||||
Salt []byte
|
||||
IterationCount int
|
||||
KeyLength *int
|
||||
Prf struct {
|
||||
asn1.ObjectIdentifier // always be idHmacWithSm3
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (p *PBKDF2) MarshalASN1() ([]byte, error) {
|
||||
var b cryptobyte.Builder
|
||||
b.AddASN1(cryptobyte_asn1.SEQUENCE, func(b *cryptobyte.Builder) {
|
||||
b.AddASN1OctetString(p.Param.Salt)
|
||||
b.AddASN1Int64(int64(p.Param.IterationCount))
|
||||
if p.Param.KeyLength != nil {
|
||||
b.AddASN1Int64(int64(*p.Param.KeyLength))
|
||||
}
|
||||
b.AddASN1(cryptobyte_asn1.SEQUENCE, func(b *cryptobyte.Builder) {
|
||||
b.AddASN1ObjectIdentifier(p.Param.Prf.ObjectIdentifier)
|
||||
})
|
||||
})
|
||||
return b.Bytes()
|
||||
}
|
||||
|
||||
func (p *PBKDF2) UnmarshalASN1(data []byte) (rest []byte, err error) {
|
||||
input := cryptobyte.String(data)
|
||||
var inner cryptobyte.String
|
||||
var paramString cryptobyte.String
|
||||
var algIdString cryptobyte.String
|
||||
|
||||
if !input.ReadASN1(&inner, cryptobyte_asn1.SEQUENCE) ||
|
||||
!inner.ReadASN1ObjectIdentifier(&p.ObjectIdentifier) ||
|
||||
!inner.ReadASN1(¶mString, cryptobyte_asn1.SEQUENCE) ||
|
||||
!inner.Empty() ||
|
||||
!paramString.ReadASN1Bytes(&p.Param.Salt, cryptobyte_asn1.OCTET_STRING) ||
|
||||
!paramString.ReadASN1Integer(&p.Param.IterationCount) {
|
||||
return data, gerrors.WithAnnotating(ErrInvalidInput, "read ASN.1 SEQUENCE failed")
|
||||
}
|
||||
if paramString.PeekASN1Tag(cryptobyte_asn1.INTEGER) {
|
||||
keyLength := 0
|
||||
if !paramString.ReadASN1Integer(&keyLength) {
|
||||
return data, gerrors.WithAnnotating(ErrInvalidInput, "read ASN.1 SEQUENCE failed")
|
||||
}
|
||||
if p.Param.KeyLength == nil {
|
||||
p.Param.KeyLength = new(int)
|
||||
}
|
||||
*p.Param.KeyLength = keyLength
|
||||
}
|
||||
if !paramString.ReadASN1(&algIdString, cryptobyte_asn1.SEQUENCE) ||
|
||||
!paramString.Empty() ||
|
||||
!algIdString.ReadASN1ObjectIdentifier(&p.Param.Prf.ObjectIdentifier) ||
|
||||
!algIdString.Empty() {
|
||||
return data, gerrors.WithAnnotating(ErrInvalidInput, "read ASN.1 SEQUENCE failed")
|
||||
}
|
||||
return input, nil
|
||||
}
|
||||
|
||||
type PBES2 struct {
|
||||
asn1.ObjectIdentifier
|
||||
Param struct {
|
||||
KeyDerivationFunc PBKDF2
|
||||
EncryptionScheme struct {
|
||||
asn1.ObjectIdentifier // 1.2.156.10197.1.104.2 (SM4_CBC, GmSSL, but not the same with GM/T 0091)
|
||||
iv []byte // The IV, always 16 bytes
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (p *PBES2) Salt() []byte {
|
||||
return p.Param.KeyDerivationFunc.Param.Salt
|
||||
}
|
||||
|
||||
func (p *PBES2) IterationCount() int {
|
||||
return p.Param.KeyDerivationFunc.Param.IterationCount
|
||||
}
|
||||
|
||||
func (p *PBES2) IV() []byte {
|
||||
return p.Param.EncryptionScheme.iv
|
||||
}
|
||||
|
||||
func (p *PBES2) MarshalASN1() ([]byte, error) {
|
||||
var b cryptobyte.Builder
|
||||
b.AddASN1(cryptobyte_asn1.SEQUENCE, func(b *cryptobyte.Builder) {
|
||||
b.AddASN1ObjectIdentifier(p.ObjectIdentifier)
|
||||
b.AddASN1(cryptobyte_asn1.SEQUENCE, func(b *cryptobyte.Builder) {
|
||||
b.MarshalASN1(&p.Param.KeyDerivationFunc)
|
||||
b.AddASN1(cryptobyte_asn1.SEQUENCE, func(b *cryptobyte.Builder) {
|
||||
b.AddASN1ObjectIdentifier(p.Param.EncryptionScheme.ObjectIdentifier)
|
||||
b.AddASN1OctetString(p.Param.EncryptionScheme.iv)
|
||||
})
|
||||
})
|
||||
})
|
||||
return b.Bytes()
|
||||
}
|
||||
|
||||
func (p *PBES2) UnmarshalASN1(data []byte) ([]byte, error) {
|
||||
input := cryptobyte.String(data)
|
||||
var inner cryptobyte.String
|
||||
var paramInner cryptobyte.String
|
||||
var encryptionSchemeString cryptobyte.String
|
||||
|
||||
if !input.ReadASN1(&inner, cryptobyte_asn1.SEQUENCE) ||
|
||||
!inner.ReadASN1ObjectIdentifier(&p.ObjectIdentifier) ||
|
||||
!inner.ReadASN1(¶mInner, cryptobyte_asn1.SEQUENCE) ||
|
||||
!inner.Empty() {
|
||||
return data, gerrors.WithAnnotating(ErrInvalidInput, "read ASN.1 SEQUENCE failed")
|
||||
}
|
||||
|
||||
rest, err := p.Param.KeyDerivationFunc.UnmarshalASN1(paramInner)
|
||||
if err != nil {
|
||||
return data, gerrors.WithAnnotating(ErrInvalidInput, "read ASN.1 SEQUENCE failed")
|
||||
}
|
||||
encryptionSchemeString = cryptobyte.String(rest)
|
||||
if !encryptionSchemeString.ReadASN1(&inner, cryptobyte_asn1.SEQUENCE) ||
|
||||
!encryptionSchemeString.Empty() ||
|
||||
!inner.ReadASN1ObjectIdentifier(&p.Param.EncryptionScheme.ObjectIdentifier) ||
|
||||
!inner.ReadASN1Bytes(&p.Param.EncryptionScheme.iv, cryptobyte_asn1.OCTET_STRING) ||
|
||||
!inner.Empty() {
|
||||
return data, gerrors.WithAnnotating(ErrInvalidInput, "read ASN.1 SEQUENCE failed")
|
||||
}
|
||||
return input, nil
|
||||
}
|
||||
Reference in New Issue
Block a user