...

Source file src/github.com/cloudflare/circl/pke/kyber/kyber1024/internal/cpapke.go

Documentation: github.com/cloudflare/circl/pke/kyber/kyber1024/internal

     1  // Code generated from kyber512/internal/cpapke.go by gen.go
     2  
     3  package internal
     4  
     5  import (
     6  	"github.com/cloudflare/circl/internal/sha3"
     7  	"github.com/cloudflare/circl/pke/kyber/internal/common"
     8  )
     9  
    10  // A Kyber.CPAPKE private key.
    11  type PrivateKey struct {
    12  	sh Vec // NTT(s), normalized
    13  }
    14  
    15  // A Kyber.CPAPKE public key.
    16  type PublicKey struct {
    17  	rho [32]byte // ρ, the seed for the matrix A
    18  	th  Vec      // NTT(t), normalized
    19  
    20  	// cached values
    21  	aT Mat // the matrix Aᵀ
    22  }
    23  
    24  // Packs the private key to buf.
    25  func (sk *PrivateKey) Pack(buf []byte) {
    26  	sk.sh.Pack(buf)
    27  }
    28  
    29  // Unpacks the private key from buf.
    30  func (sk *PrivateKey) Unpack(buf []byte) {
    31  	sk.sh.Unpack(buf)
    32  	sk.sh.Normalize()
    33  }
    34  
    35  // Packs the public key to buf.
    36  func (pk *PublicKey) Pack(buf []byte) {
    37  	pk.th.Pack(buf)
    38  	copy(buf[K*common.PolySize:], pk.rho[:])
    39  }
    40  
    41  // Unpacks the public key from buf.
    42  func (pk *PublicKey) Unpack(buf []byte) {
    43  	pk.th.Unpack(buf)
    44  	pk.th.Normalize()
    45  	copy(pk.rho[:], buf[K*common.PolySize:])
    46  	pk.aT.Derive(&pk.rho, true)
    47  }
    48  
    49  // Derives a new Kyber.CPAPKE keypair from the given seed.
    50  func NewKeyFromSeed(seed []byte) (*PublicKey, *PrivateKey) {
    51  	var pk PublicKey
    52  	var sk PrivateKey
    53  
    54  	var expandedSeed [64]byte
    55  
    56  	h := sha3.New512()
    57  	_, _ = h.Write(seed)
    58  
    59  	// This writes hash into expandedSeed.  Yes, this is idiomatic Go.
    60  	_, _ = h.Read(expandedSeed[:])
    61  
    62  	copy(pk.rho[:], expandedSeed[:32])
    63  	sigma := expandedSeed[32:] // σ, the noise seed
    64  
    65  	pk.aT.Derive(&pk.rho, false) // Expand ρ to matrix A; we'll transpose later
    66  
    67  	var eh Vec
    68  	sk.sh.DeriveNoise(sigma, 0, Eta1) // Sample secret vector s
    69  	sk.sh.NTT()
    70  	sk.sh.Normalize()
    71  
    72  	eh.DeriveNoise(sigma, K, Eta1) // Sample blind e
    73  	eh.NTT()
    74  
    75  	// Next, we compute t = A s + e.
    76  	for i := 0; i < K; i++ {
    77  		// Note that coefficients of s are bounded by q and those of A
    78  		// are bounded by 4.5q and so their product is bounded by 2¹⁵q
    79  		// as required for multiplication.
    80  		PolyDotHat(&pk.th[i], &pk.aT[i], &sk.sh)
    81  
    82  		// A and s were not in Montgomery form, so the Montgomery
    83  		// multiplications in the inner product added a factor R⁻¹ which
    84  		// we'll cancel out now.  This will also ensure the coefficients of
    85  		// t are bounded in absolute value by q.
    86  		pk.th[i].ToMont()
    87  	}
    88  
    89  	pk.th.Add(&pk.th, &eh) // bounded by 8q.
    90  	pk.th.Normalize()
    91  	pk.aT.Transpose()
    92  
    93  	return &pk, &sk
    94  }
    95  
    96  // Decrypts ciphertext ct meant for private key sk to plaintext pt.
    97  func (sk *PrivateKey) DecryptTo(pt, ct []byte) {
    98  	var u Vec
    99  	var v, m common.Poly
   100  
   101  	u.Decompress(ct, DU)
   102  	v.Decompress(ct[K*compressedPolySize(DU):], DV)
   103  
   104  	// Compute m = v - <s, u>
   105  	u.NTT()
   106  	PolyDotHat(&m, &sk.sh, &u)
   107  	m.BarrettReduce()
   108  	m.InvNTT()
   109  	m.Sub(&v, &m)
   110  	m.Normalize()
   111  
   112  	// Compress polynomial m to original message
   113  	m.CompressMessageTo(pt)
   114  }
   115  
   116  // Encrypts message pt for the public key to ciphertext ct using randomness
   117  // from seed.
   118  //
   119  // seed has to be of length SeedSize, pt of PlaintextSize and ct of
   120  // CiphertextSize.
   121  func (pk *PublicKey) EncryptTo(ct, pt, seed []byte) {
   122  	var rh, e1, u Vec
   123  	var e2, v, m common.Poly
   124  
   125  	// Sample r, e₁ and e₂ from B_η
   126  	rh.DeriveNoise(seed, 0, Eta1)
   127  	rh.NTT()
   128  	rh.BarrettReduce()
   129  
   130  	e1.DeriveNoise(seed, K, common.Eta2)
   131  	e2.DeriveNoise(seed, 2*K, common.Eta2)
   132  
   133  	// Next we compute u = Aᵀ r + e₁.  First Aᵀ.
   134  	for i := 0; i < K; i++ {
   135  		// Note that coefficients of r are bounded by q and those of Aᵀ
   136  		// are bounded by 4.5q and so their product is bounded by 2¹⁵q
   137  		// as required for multiplication.
   138  		PolyDotHat(&u[i], &pk.aT[i], &rh)
   139  	}
   140  
   141  	u.BarrettReduce()
   142  
   143  	// Aᵀ and r were not in Montgomery form, so the Montgomery
   144  	// multiplications in the inner product added a factor R⁻¹ which
   145  	// the InvNTT cancels out.
   146  	u.InvNTT()
   147  
   148  	u.Add(&u, &e1) // u = Aᵀ r + e₁
   149  
   150  	// Next compute v = <t, r> + e₂ + Decompress_q(m, 1).
   151  	PolyDotHat(&v, &pk.th, &rh)
   152  	v.BarrettReduce()
   153  	v.InvNTT()
   154  
   155  	m.DecompressMessage(pt)
   156  	v.Add(&v, &m)
   157  	v.Add(&v, &e2) // v = <t, r> + e₂ + Decompress_q(m, 1)
   158  
   159  	// Pack ciphertext
   160  	u.Normalize()
   161  	v.Normalize()
   162  
   163  	u.CompressTo(ct, DU)
   164  	v.CompressTo(ct[K*compressedPolySize(DU):], DV)
   165  }
   166  
   167  // Returns whether sk equals other.
   168  func (sk *PrivateKey) Equal(other *PrivateKey) bool {
   169  	ret := int16(0)
   170  	for i := 0; i < K; i++ {
   171  		for j := 0; j < common.N; j++ {
   172  			ret |= sk.sh[i][j] ^ other.sh[i][j]
   173  		}
   174  	}
   175  	return ret == 0
   176  }
   177  

View as plain text