go test -count 1 -timeout 10s -v -race github.com/qydysky/part/slice
go test -count 1 -timeout 5s -v -race github.com/qydysky/part/bools
go test -count 1 -timeout 5s -v -race github.com/qydysky/part/errors
- go test -count 1 -timeout 5s -v -race github.com/qydysky/part/crypto
+ go test -count 1 -timeout 5s -v -race github.com/qydysky/part/crypto/...
go test -count 1 -timeout 5s -v -race github.com/qydysky/part/flag -sss=ss -i32=32 -f34=34 -btrue=true -d1m=1m
w-test:
go test -count 1 -timeout 10s -v -race github.com/qydysky/part/slice
go test -count 1 -timeout 5s -v -race github.com/qydysky/part/bools
go test -count 1 -timeout 5s -v -race github.com/qydysky/part/errors
- go test -count 1 -timeout 5s -v -race github.com/qydysky/part/crypto
+ go test -count 1 -timeout 5s -v -race github.com/qydysky/part/crypto/...
go test -count 1 -timeout 5s -v -race github.com/qydysky/part/flag -sss=ss -i32=32 -f34=34 -btrue=true -d1m=1m
u-test:
go test -count 1 -timeout 10s -v -race github.com/qydysky/part/slice
go test -count 1 -timeout 5s -v -race github.com/qydysky/part/bools
go test -count 1 -timeout 5s -v -race github.com/qydysky/part/errors
- go test -count 1 -timeout 5s -v -race github.com/qydysky/part/crypto
+ go test -count 1 -timeout 5s -v -race github.com/qydysky/part/crypto/...
go test -count 1 -timeout 5s -v -race github.com/qydysky/part/flag -sss=ss -i32=32 -f34=34 -btrue=true -d1m=1m
ErrPemType = errors.New(`ErrPemType`)
)
+// Deprecated: 使用 asymmetric 包
func NewKey() (pri, pub []byte, e error) {
if p1, e := ecdh.X25519().GenerateKey(rand.Reader); e != nil {
return nil, nil, e
}
}
+// Deprecated: 使用 asymmetric 包
func Encrypt(msg, pubKey []byte) (b []byte, e error) {
c := ecdh.X25519()
var (
return
}
+// Deprecated: 使用 asymmetric 包
func Decrypt(b, priKey []byte) (msg []byte, e error) {
var (
q1 *ecdh.PublicKey
--- /dev/null
+package part
+
+import (
+ "crypto/mlkem"
+ "encoding/pem"
+
+ pc "github.com/qydysky/part/crypto"
+)
+
+type Mlkem struct{}
+
+var MlkemF pc.Asymmetric = Mlkem{}
+
+func (t Mlkem) GetType() string {
+ return `MLKEM`
+}
+func (t Mlkem) CheckType(b *pem.Block) (ok bool, isPriKey bool) {
+ isPriKey = b.Type == t.GetType()+PriKeySuf
+ if !isPriKey {
+ ok = b.Type == t.GetType()+PubKeySuf
+ } else {
+ ok = true
+ }
+ return
+}
+
+func (t Mlkem) Decrypt(priKey *pem.Block) (dec pc.AsymmetricDec, e error) {
+ if priKey.Type != t.GetType()+PriKeySuf {
+ return nil, ErrType
+ } else if d, err := mlkem.NewDecapsulationKey1024(priKey.Bytes); err != nil {
+ return nil, err
+ } else {
+ return func(sym pc.Symmetric, b, exchangeTxt []byte) (msg []byte, e error) {
+ if sharedKey, err := d.Decapsulate(exchangeTxt); err != nil {
+ return nil, err
+ } else {
+ return sym.Decrypt(b, sharedKey)
+ }
+ }, nil
+ }
+}
+
+func (t Mlkem) Encrypt(pubKey *pem.Block) (enc pc.AsymmetricEnc, e error) {
+ if pubKey.Type != t.GetType()+PubKeySuf {
+ return nil, ErrType
+ } else if d, err := mlkem.NewEncapsulationKey1024(pubKey.Bytes); err != nil {
+ return nil, err
+ } else {
+ return func(sym pc.Symmetric, msg []byte) (b, exchangeTxt []byte, e error) {
+ sharedKey, ciphertext := d.Encapsulate()
+ b, e = sym.Encrypt(msg, sharedKey)
+ if e != nil {
+ return nil, nil, e
+ }
+ return b, ciphertext, nil
+ }, nil
+ }
+}
+
+func (t Mlkem) NewKey() (pri, pub *pem.Block, e error) {
+ var d *mlkem.DecapsulationKey1024
+ d, e = mlkem.GenerateKey1024()
+ if e != nil {
+ return
+ }
+ return &pem.Block{
+ Type: t.GetType() + PriKeySuf,
+ Bytes: d.Bytes(),
+ }, &pem.Block{
+ Type: t.GetType() + PubKeySuf,
+ Bytes: d.EncapsulationKey().Bytes(),
+ }, nil
+}
--- /dev/null
+package part
+
+import (
+ "bytes"
+ "crypto/rand"
+ "testing"
+
+ pcs "github.com/qydysky/part/crypto/symmetric"
+)
+
+func Test_Mlkem(t *testing.T) {
+ var buf = make([]byte, 100)
+ if n, e := rand.Read(buf); e != nil {
+ t.Fatal(e)
+ } else {
+ buf = buf[:n]
+ }
+
+ m := MlkemF
+ sym := pcs.Chacha20poly1305F
+ if pri, pub, e := MlkemF.NewKey(); e != nil {
+ t.Fatal(e)
+ } else {
+ if enc, e := m.Encrypt(pub); e != nil {
+ t.Fatal(e)
+ } else if b, ex, e := enc(sym, buf); e != nil {
+ t.Fatal()
+ } else {
+ b, ex = Unpack(Pack(b, ex))
+ if dec, e := m.Decrypt(pri); e != nil {
+ t.Fatal(e)
+ } else if msg, e := dec(sym, b, ex); e != nil {
+ t.Fatal(e)
+ } else if !bytes.Equal(msg, buf) {
+ t.Fatal()
+ }
+ }
+ }
+}
--- /dev/null
+package part
+
+import (
+ "encoding/pem"
+ "errors"
+
+ pc "github.com/qydysky/part/crypto"
+)
+
+var (
+ PriKeySuf string = ` PRIVATE KEY`
+ PubKeySuf string = ` PUBLIC KEY`
+ ErrType error = errors.New(`ErrType`)
+)
+
+func ChoseAsymmetricByPem(b *pem.Block) pc.Asymmetric {
+ if ok, _ := X25519F.CheckType(b); ok {
+ return X25519F
+ } else if ok, _ := MlkemF.CheckType(b); ok {
+ return MlkemF
+ } else {
+ return nil
+ }
+}
+
+func Pack(b, exchangeTxt []byte) (a []byte) {
+ buf := make([]byte, 4+len(exchangeTxt)+len(b))
+ n := copy(buf, itob32(int32(len(exchangeTxt))))
+ n += copy(buf[n:], exchangeTxt)
+ copy(buf[n:], b)
+ return buf
+}
+
+func Unpack(a []byte) (b, exchangeTxt []byte) {
+ exL := btoi32(a[:4])
+ return a[4+exL:], a[4 : 4+exL]
+}
+
+func itob32(v int32) []byte {
+ //binary.BigEndian.PutUint32
+ b := make([]byte, 4)
+ b[0] = byte(v >> 24)
+ b[1] = byte(v >> 16)
+ b[2] = byte(v >> 8)
+ b[3] = byte(v)
+ return b
+}
+
+func btoi32(bu []byte) uint32 {
+ return uint32(bu[3]) | uint32(bu[2])<<8 | uint32(bu[1])<<16 | uint32(bu[0])<<24
+}
--- /dev/null
+package part
+
+import (
+ "crypto/ecdh"
+ "crypto/rand"
+ "encoding/pem"
+
+ pc "github.com/qydysky/part/crypto"
+)
+
+var X25519F pc.Asymmetric = X25519{}
+
+type X25519 struct{}
+
+// CheckType implements part.Asymmetric.
+func (t X25519) CheckType(b *pem.Block) (ok bool, isPriKey bool) {
+ isPriKey = b.Type == t.GetType()+PriKeySuf
+ if !isPriKey {
+ ok = b.Type == t.GetType()+PubKeySuf
+ } else {
+ ok = true
+ }
+ return
+}
+
+func (t X25519) GetType() string {
+ return `ECDH` // 为了保证向后兼容,此处为ECDH
+}
+
+func (t X25519) Decrypt(priKey *pem.Block) (dec pc.AsymmetricDec, e error) {
+ if priKey.Type != t.GetType()+PriKeySuf {
+ return nil, ErrType
+ }
+
+ var p2 *ecdh.PrivateKey
+ if p2, e = ecdh.X25519().NewPrivateKey(priKey.Bytes); e != nil {
+ return
+ }
+
+ return func(sym pc.Symmetric, b, exchangeTxt []byte) (msg []byte, e error) {
+ if q1, err := ecdh.X25519().NewPublicKey(exchangeTxt); err != nil {
+ return nil, err
+ } else if key, err := p2.ECDH(q1); err != nil {
+ return nil, err
+ } else {
+ return sym.Decrypt(b, key)
+ }
+ }, nil
+}
+
+func (t X25519) Encrypt(pubKey *pem.Block) (enc pc.AsymmetricEnc, e error) {
+ if pubKey.Type != t.GetType()+PubKeySuf {
+ return nil, ErrType
+ }
+
+ var (
+ p1 *ecdh.PrivateKey
+ q1 *ecdh.PublicKey
+ q2 *ecdh.PublicKey
+ key []byte
+ )
+ if p1, e = ecdh.X25519().GenerateKey(rand.Reader); e != nil {
+ return
+ }
+ q1 = p1.PublicKey()
+ if q2, e = ecdh.X25519().NewPublicKey(pubKey.Bytes); e != nil {
+ return
+ } else if key, e = p1.ECDH(q2); e != nil {
+ return
+ } else {
+ return func(sym pc.Symmetric, msg []byte) (b []byte, exchangeTxt []byte, e error) {
+ b, e = sym.Encrypt(msg, key)
+ exchangeTxt = q1.Bytes()
+ return
+ }, nil
+ }
+}
+
+func (t X25519) NewKey() (pri, pub *pem.Block, e error) {
+ if d, e := ecdh.X25519().GenerateKey(rand.Reader); e != nil {
+ return nil, nil, e
+ } else {
+ return &pem.Block{
+ Type: t.GetType() + PriKeySuf,
+ Bytes: d.Bytes(),
+ }, &pem.Block{
+ Type: t.GetType() + PubKeySuf,
+ Bytes: d.PublicKey().Bytes(),
+ }, nil
+ }
+}
--- /dev/null
+package part
+
+import (
+ "bytes"
+ "crypto/rand"
+ "testing"
+
+ pcs "github.com/qydysky/part/crypto/symmetric"
+)
+
+func Test_X25519(t *testing.T) {
+ var buf = make([]byte, 100)
+ if n, e := rand.Read(buf); e != nil {
+ t.Fatal(e)
+ } else {
+ buf = buf[:n]
+ }
+
+ m := X25519F
+ sym := pcs.Chacha20poly1305F
+ if pri, pub, e := m.NewKey(); e != nil {
+ t.Fatal(e)
+ } else {
+ if enc, e := m.Encrypt(pub); e != nil {
+ t.Fatal(e)
+ } else if b, ex, e := enc(sym, buf); e != nil {
+ t.Fatal()
+ } else {
+ b, ex = Unpack(Pack(b, ex))
+ if dec, e := m.Decrypt(pri); e != nil {
+ t.Fatal(e)
+ } else if msg, e := dec(sym, b, ex); e != nil {
+ t.Fatal(e)
+ } else if !bytes.Equal(msg, buf) {
+ t.Fatal()
+ }
+ }
+ }
+}
--- /dev/null
+package part
+
+import (
+ "encoding/pem"
+)
+
+type Asymmetric interface {
+ GetType() string
+ CheckType(b *pem.Block) (ok bool, isPriKey bool)
+ NewKey() (pri, pub *pem.Block, e error)
+ Encrypt(pubKey *pem.Block) (enc AsymmetricEnc, e error)
+ Decrypt(priKey *pem.Block) (dec AsymmetricDec, e error)
+}
+
+// func(sym Symmetric, msg []byte) (b, exchangeTxt []byte, e error)
+type AsymmetricEnc func(sym Symmetric, msg []byte) (b, exchangeTxt []byte, e error)
+
+// func(sym Symmetric, b, exchangeTxt []byte) (msg []byte, e error)
+type AsymmetricDec func(sym Symmetric, b, exchangeTxt []byte) (msg []byte, e error)
+
+type Symmetric interface {
+ GetType() string
+ Encrypt(msg, key []byte) (b []byte, e error)
+ Decrypt(b, key []byte) (msg []byte, e error)
+}
--- /dev/null
+package part
+
+import (
+ "crypto/rand"
+
+ pcrypto "github.com/qydysky/part/crypto"
+ "golang.org/x/crypto/chacha20poly1305"
+)
+
+type Chacha20poly1305 struct{}
+
+var Chacha20poly1305F pcrypto.Symmetric = Chacha20poly1305{}
+
+// GetType implements part.Symmetric.
+func (c Chacha20poly1305) GetType() string {
+ return `CHACHA20POLY1305`
+}
+
+// Decrypt implements part.Symmetric.
+func (c Chacha20poly1305) Decrypt(b []byte, key []byte) (msg []byte, e error) {
+ if aead, err := chacha20poly1305.NewX(key); err != nil {
+ return nil, err
+ } else {
+ nonce, ciphertext := b[:aead.NonceSize()], b[aead.NonceSize():]
+ return aead.Open(nil, nonce, ciphertext, nil)
+ }
+}
+
+// Encrypt implements part.Symmetric.
+func (c Chacha20poly1305) Encrypt(msg []byte, key []byte) (b []byte, e error) {
+ if aead, err := chacha20poly1305.NewX(key); err != nil {
+ return nil, err
+ } else {
+ nonce := make([]byte, aead.NonceSize(), aead.NonceSize()+len(msg)+aead.Overhead())
+ if n, err := rand.Read(nonce); err != nil {
+ return nil, err
+ } else {
+ nonce = nonce[:n]
+ return aead.Seal(nonce, nonce, msg, nil), nil
+ }
+ }
+}