File: scheme.go

package info (click to toggle)
golang-github-cloudflare-circl 1.6.1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 18,064 kB
  • sloc: asm: 20,492; ansic: 1,292; makefile: 68
file content (140 lines) | stat: -rw-r--r-- 3,395 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
package xwing

import (
	"bytes"
	cryptoRand "crypto/rand"
	"crypto/subtle"

	"github.com/cloudflare/circl/kem"
	"github.com/cloudflare/circl/kem/mlkem/mlkem768"
)

// This file contains the boilerplate code to connect X-Wing to the
// generic KEM API.

// Returns the generic KEM interface for  X-Wing PQ/T hybrid KEM.
func Scheme() kem.Scheme { return scheme{} }

type scheme struct{}

func (scheme) Name() string               { return "X-Wing" }
func (scheme) PublicKeySize() int         { return PublicKeySize }
func (scheme) PrivateKeySize() int        { return PrivateKeySize }
func (scheme) SeedSize() int              { return SeedSize }
func (scheme) EncapsulationSeedSize() int { return EncapsulationSeedSize }
func (scheme) SharedKeySize() int         { return SharedKeySize }
func (scheme) CiphertextSize() int        { return CiphertextSize }
func (*PrivateKey) Scheme() kem.Scheme    { return scheme{} }
func (*PublicKey) Scheme() kem.Scheme     { return scheme{} }

func (sch scheme) Encapsulate(pk kem.PublicKey) (ct, ss []byte, err error) {
	var seed [EncapsulationSeedSize]byte
	_, err = cryptoRand.Read(seed[:])
	if err != nil {
		return
	}
	return sch.EncapsulateDeterministically(pk, seed[:])
}

func (scheme) EncapsulateDeterministically(
	pk kem.PublicKey, seed []byte,
) ([]byte, []byte, error) {
	if len(seed) != EncapsulationSeedSize {
		return nil, nil, kem.ErrSeedSize
	}
	pub, ok := pk.(*PublicKey)
	if !ok {
		return nil, nil, kem.ErrTypeMismatch
	}
	var (
		ct [CiphertextSize]byte
		ss [SharedKeySize]byte
	)
	pub.EncapsulateTo(ct[:], ss[:], seed)
	return ct[:], ss[:], nil
}

func (scheme) UnmarshalBinaryPublicKey(buf []byte) (kem.PublicKey, error) {
	var pk PublicKey
	if len(buf) != PublicKeySize {
		return nil, kem.ErrPubKeySize
	}

	if err := pk.Unpack(buf); err != nil {
		return nil, err
	}
	return &pk, nil
}

func (scheme) UnmarshalBinaryPrivateKey(buf []byte) (kem.PrivateKey, error) {
	var sk PrivateKey
	if len(buf) != PrivateKeySize {
		return nil, kem.ErrPrivKeySize
	}

	sk.Unpack(buf)
	return &sk, nil
}

func (sk *PrivateKey) MarshalBinary() ([]byte, error) {
	var ret [PrivateKeySize]byte
	sk.Pack(ret[:])
	return ret[:], nil
}

func (sk *PrivateKey) Equal(other kem.PrivateKey) bool {
	oth, ok := other.(*PrivateKey)
	if !ok {
		return false
	}
	return sk.m.Equal(&oth.m) &&
		subtle.ConstantTimeCompare(oth.x[:], sk.x[:]) == 1
}

func (sk *PrivateKey) Public() kem.PublicKey {
	var pk PublicKey
	pk.m = *(sk.m.Public().(*mlkem768.PublicKey))
	pk.x = sk.xpk
	return &pk
}

func (pk *PublicKey) Equal(other kem.PublicKey) bool {
	oth, ok := other.(*PublicKey)
	if !ok {
		return false
	}
	return pk.m.Equal(&oth.m) && bytes.Equal(pk.x[:], oth.x[:])
}

func (pk *PublicKey) MarshalBinary() ([]byte, error) {
	var ret [PublicKeySize]byte
	pk.Pack(ret[:])
	return ret[:], nil
}

func (scheme) DeriveKeyPair(seed []byte) (kem.PublicKey, kem.PrivateKey) {
	sk, pk := DeriveKeyPair(seed)
	return pk, sk
}

func (scheme) GenerateKeyPair() (kem.PublicKey, kem.PrivateKey, error) {
	sk, pk, err := GenerateKeyPair(nil)
	return pk, sk, err
}

func (scheme) Decapsulate(sk kem.PrivateKey, ct []byte) ([]byte, error) {
	if len(ct) != CiphertextSize {
		return nil, kem.ErrCiphertextSize
	}

	var ss [SharedKeySize]byte

	priv, ok := sk.(*PrivateKey)
	if !ok {
		return nil, kem.ErrTypeMismatch
	}

	priv.DecapsulateTo(ss[:], ct[:])

	return ss[:], nil
}