Skip to content

Commit

Permalink
Implement against side-channel.
Browse files Browse the repository at this point in the history
  • Loading branch information
Yuncong Zhang committed Dec 22, 2017
1 parent af95adf commit ff6e5ed
Show file tree
Hide file tree
Showing 12 changed files with 1,463 additions and 376 deletions.
6 changes: 3 additions & 3 deletions key_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ package bliss

import (
"fmt"
"io/ioutil"
"github.com/LoCCS/bliss/sampler"
"io/ioutil"
"reflect"
"strconv"
"strings"
"testing"
"reflect"
)

func TestGeneratePrivateKey(t *testing.T) {
Expand Down Expand Up @@ -152,4 +152,4 @@ func TestKeySerialization(t *testing.T) {
}
}
}
}
}
29 changes: 29 additions & 0 deletions poly/polyarray.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,3 +111,32 @@ func GaussPoly(version int, s *sampler.Sampler) *PolyArray {
p.SetData(v)
return p
}

// For splitted version
func GaussPolyAlpha(version int, s *sampler.Sampler) *PolyArray {
p, err := New(version)
if err != nil {
return nil
}
n := p.param.N
v := make([]int32, n)
for i := 0; i < int(n); i++ {
v[i] = s.SampleGaussCtAlpha()
}
p.SetData(v)
return p
}

func GaussPolyBeta(version int, s *sampler.Sampler) *PolyArray {
p, err := New(version)
if err != nil {
return nil
}
n := p.param.N
v := make([]int32, n)
for i := 0; i < int(n); i++ {
v[i] = s.SampleGaussCtBeta()
}
p.SetData(v)
return p
}
180 changes: 150 additions & 30 deletions sampler/sampler.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (
"github.com/LoCCS/bliss/params"
)


type Sampler struct {
sigma uint32
ell uint32
Expand All @@ -14,47 +13,87 @@ type Sampler struct {
kSigma uint16
kSigmaBits uint16

ctable []uint8
cdttable []uint8
ctable []uint8

/* For splitting */
ell1 uint32
ell2 uint32
kSigma1 uint16
kSigma2 uint16
kSigmaBits1 uint16
kSigmaBits2 uint16
ctable1 []uint8
ctable2 []uint8

random *Entropy
}

func invalidSampler() *Sampler {
return &Sampler{0,0,0,0,0,0,[]uint8{},[]uint8{},nil}
return &Sampler{0, 0, 0, 0, 0, 0, []uint8{}, 0, 0, 0, 0, 0, 0,
[]uint8{}, []uint8{}, nil}
}

func NewSampler(sigma,ell,prec uint32, entropy *Entropy) (*Sampler, error) {
columns := prec/8
ctable,err := getTable(sigma,ell,prec)
func NewSampler(sigma, ell, prec uint32, entropy *Entropy) (*Sampler, error) {
columns := prec / 8
ctable, err := getTable(sigma, ell, prec)
if err != nil {
return invalidSampler(),err
return invalidSampler(), err
}
ksigma := getKSigma(sigma,prec)
ksigma := getKSigma(sigma, prec)
if ksigma == 0 {
return invalidSampler(),fmt.Errorf("Failed to get kSigma")
return invalidSampler(), fmt.Errorf("Failed to get kSigma")
}
ksigmabits := getKSigmaBits(sigma,prec)
ksigmabits := getKSigmaBits(sigma, prec)
if ksigmabits == 0 {
return invalidSampler(),fmt.Errorf("Failed to get kSigmaBits")
return invalidSampler(), fmt.Errorf("Failed to get kSigmaBits")
}
sigma1, sigma2, ell1, ell2 := splitSigma(sigma)
if sigma1 == 0 || sigma2 == 0 || ell1 == 0 || ell2 == 0 {
return invalidSampler(), fmt.Errorf("Failed to split sigma")
}
ctable1, err := getTable(sigma1, ell1, prec)
if err != nil {
return invalidSampler(), err
}
ksigma1 := getKSigma(sigma1, prec)
if ksigma1 == 0 {
return invalidSampler(), fmt.Errorf("Failed to get kSigma1")
}
return &Sampler{sigma,ell,prec,columns,ksigma,ksigmabits,ctable,[]uint8{},entropy},nil
ksigmabits1 := getKSigmaBits(sigma1, prec)
if ksigmabits1 == 0 {
return invalidSampler(), fmt.Errorf("Failed to get kSigmaBits1")
}
ctable2, err := getTable(sigma2, ell2, prec)
if err != nil {
return invalidSampler(), err
}
ksigma2 := getKSigma(sigma2, prec)
if ksigma2 == 0 {
return invalidSampler(), fmt.Errorf("Failed to get kSigma2")
}
ksigmabits2 := getKSigmaBits(sigma2, prec)
if ksigmabits2 == 0 {
return invalidSampler(), fmt.Errorf("Failed to get kSigmaBits2")
}
return &Sampler{sigma, ell, prec, columns, ksigma, ksigmabits, ctable,
ell1, ell2, ksigma1, ksigma2, ksigmabits1, ksigmabits2, ctable1, ctable2,
entropy}, nil
}

func New(version int, entropy *Entropy) (*Sampler, error) {
param := params.GetParam(version)
if param == nil {
return nil,fmt.Errorf("Failed to get parameter")
return nil, fmt.Errorf("Failed to get parameter")
}
return NewSampler(param.Sigma,param.Ell,param.Prec,entropy)
return NewSampler(param.Sigma, param.Ell, param.Prec, entropy)
}

// Sample Bernoulli distribution with probability p
// p is stored as a large big-endian integer in an array
// the real probability is p/2^d, where d is the number of
// bits of p
func (sampler *Sampler) sampleBer(p []uint8) bool {
for _,pi := range p {
for _, pi := range p {
uc := sampler.random.Char()
if uc < pi {
return true
Expand All @@ -67,13 +106,13 @@ func (sampler *Sampler) sampleBer(p []uint8) bool {
}

// Sample Bernoulli distribution with probability p = exp(-x/(2*sigma^2))
func (sampler *Sampler) SampleBerExp(x uint32) bool {
ri := sampler.ell - 1
func (sampler *Sampler) sampleBerExp(x uint32, table []uint8, ell uint32) bool {
ri := ell - 1
mask := uint32(1) << ri
start := ri * sampler.columns
for mask > 0 {
if x & mask != 0 {
if !sampler.sampleBer(sampler.ctable[start:start+sampler.columns]) {
if x&mask != 0 {
if !sampler.sampleBer(table[start : start+sampler.columns]) {
return false
}
}
Expand All @@ -83,27 +122,60 @@ func (sampler *Sampler) SampleBerExp(x uint32) bool {
return true
}

// Sample Bernoulli distribution with probability p = exp(-x/(2*sigma^2))
func (sampler *Sampler) sampleBerExpCt(x uint32, table []uint8, ell uint32) bool {
var xi, i, ret, start, bit uint32
start = 0
ret = 1

xi = x
for i = ell - 1; i != 0; i-- {
if sampler.sampleBer(table[start : start+sampler.columns]) {
bit = 1
} else {
bit = 0
}
ret = ret * (1 - (xi & 1) + uint32(bit)*(xi&1))
xi >>= 1
start += sampler.columns
}

return ret != 0
}

// Sample Bernoulli distribution with probability p = 1/cosh(-x/(2*sigma^2))
func (sampler *Sampler) SampleBerCosh(x int32) bool {
func (sampler *Sampler) sampleBerCosh(x int32, table []uint8, ell uint32) bool {
if x < 0 {
x = -x
}
x <<= 1
for {
bit := sampler.SampleBerExp(uint32(x))
bit := sampler.sampleBerExp(uint32(x), table, ell)
if bit {
return true
}
bit = sampler.random.Bit()
if !bit {
bit = sampler.SampleBerExp(uint32(x))
bit = sampler.sampleBerExp(uint32(x), table, ell)
if !bit {
return false
}
}
}
}

func (sampler *Sampler) SampleBerExp(x uint32) bool {
return sampler.sampleBerExp(x, sampler.ctable, sampler.ell)
}

func (sampler *Sampler) SampleBerExpCt(x uint32) bool {
return sampler.sampleBerExpCt(x, sampler.ctable, sampler.ell)
}

func (sampler *Sampler) SampleBerCosh(x int32) bool {
return sampler.sampleBerCosh(x, sampler.ctable, sampler.ell)
}

// Discrete Binary Gauss distribution is Discrete Gauss Distribution with
// a specific variance sigma = sqrt(1/(2 ln 2)) = 0.849...
// This is used as foundation of SampleGauss.
Expand All @@ -126,30 +198,78 @@ restart:

// Sample according to Discrete Gauss Distribution
// exp(-x^2/(2*sigma*sigma))
func (sampler *Sampler) sampleGauss(ksigma uint16, ksigmabits uint16, table []uint8, ell uint32) int32 {
var x, y uint32
var u bool
for {
x = sampler.SampleBinaryGauss()
for {
y = sampler.random.Bits(int(ksigmabits))
if y < uint32(ksigma) {
break
}
}
e := y * (y + 2*uint32(ksigma)*x)
u = sampler.random.Bit()
if (x|y) != 0 || u {
if sampler.sampleBerExp(e, table, ell) {
break
}
}
}

valPos := int32(uint32(ksigma)*x + y)
if u {
return valPos
} else {
return -valPos
}
}

func (sampler *Sampler) SampleGauss() int32 {
var x,y uint32
return sampler.sampleGauss(sampler.kSigma, sampler.kSigmaBits, sampler.ctable, sampler.ell)
}

// Sample according to Discrete Gauss Distribution, constant time
// exp(-x^2/(2*sigma*sigma))
func (sampler *Sampler) sampleGaussCt(ksigma uint16, ksigmabits uint16, table []uint8, ell uint32) int32 {
var x, y uint32
var u bool
for {
x = sampler.SampleBinaryGauss()
for {
y = sampler.random.Bits(int(sampler.kSigmaBits))
if y < uint32(sampler.kSigma) {
y = sampler.random.Bits(int(ksigmabits))
if y < uint32(ksigma) {
break
}
}
e := y * (y + 2 * uint32(sampler.kSigma) * x)
e := y * (y + 2*uint32(ksigma)*x)
u = sampler.random.Bit()
if (x | y) != 0 || u {
if sampler.SampleBerExp(e) {
if (x|y) != 0 || u {
if sampler.sampleBerExpCt(e, table, ell) {
break
}
}
}

valPos := int32(uint32(sampler.kSigma) * x + y)
valPos := int32(uint32(ksigma)*x + y)
if u {
return valPos
} else {
return -valPos
}
}

func (sampler *Sampler) SampleGaussCt() int32 {
return sampler.sampleGaussCt(sampler.kSigma, sampler.kSigmaBits, sampler.ctable, sampler.ell)
}

// Sample according to Discrete Gauss Distribution, by sigma1
func (sampler *Sampler) SampleGaussCtAlpha() int32 {
return sampler.sampleGaussCt(sampler.kSigma1, sampler.kSigmaBits1, sampler.ctable1, sampler.ell1)
}

// Sample according to Discrete Gauss Distribution, by sigma2
func (sampler *Sampler) SampleGaussCtBeta() int32 {
return sampler.sampleGaussCt(sampler.kSigma2, sampler.kSigmaBits2, sampler.ctable2, sampler.ell2)
}
Loading

0 comments on commit ff6e5ed

Please sign in to comment.