Skip to content
Snippets Groups Projects
Select Git revision
  • d1eb87d65bc32d7003adecd3e763b7dbe9b1ba2c
  • release default
  • master protected
  • hotfix/gtnNoToken
  • XX-4441
  • Jakub/rootless-CI
  • jonah/refactorProviders
  • Ace/Huawei
  • AceVentura/AccountBackup
  • hotfix/delete-error
  • waitingRoundsRewrite
  • dev
  • quantumSecure
  • hotfix/ratelimit
  • fullRateLimit
  • XX-3564/TlsCipherSuite
  • hotfix/notifications-db
  • hotfix/groupNotification
  • Project/LastMile
  • notls
  • url-repo-rename
  • v2.3.0
  • v2.2.0
  • v2.1.0
  • v2.0.0
  • v1.0.0
26 results

fcm.go

  • source_test.go 10.71 KiB
    ////////////////////////////////////////////////////////////////////////////////
    // Copyright © 2022 xx foundation                                             //
    //                                                                            //
    // Use of this source code is governed by a license that can be found in the  //
    // LICENSE file.                                                              //
    ////////////////////////////////////////////////////////////////////////////////
    
    package csprng
    
    import (
    	"crypto/aes"
    	"gitlab.com/xx_network/crypto/large"
    	"os"
    	"testing"
    	"time"
    )
    
    const MODP4096 = "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" +
    	"29024E088A67CC74020BBEA63B139B22514A08798E3404DD" +
    	"EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" +
    	"E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" +
    	"EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" +
    	"C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" +
    	"83655D23DCA3AD961C62F356208552BB9ED529077096966D" +
    	"670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" +
    	"E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" +
    	"DE2BCBF6955817183995497CEA956AE515D2261898FA0510" +
    	"15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64" +
    	"ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" +
    	"ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B" +
    	"F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" +
    	"BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31" +
    	"43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7" +
    	"88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA" +
    	"2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6" +
    	"287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED" +
    	"1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9" +
    	"93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934063199" +
    	"FFFFFFFFFFFFFFFF"
    
    const MODP2048 = "9DB6FB5951B66BB6FE1E140F1D2CE5502374161FD6538DF1" +
    	"648218642F0B5C48C8F7A41AADFA187324B87674FA1822B0" +
    	"0F1ECF8136943D7C55757264E5A1A44FFE012E9936E00C1D" +
    	"3E9310B01C7D179805D3058B2A9F4BB6F9716BFE6117C6B5" +
    	"B3CC4D9BE341104AD4A80AD6C94E005F4B993E14F091EB51" +
    	"743BF33050C38DE235567E1B34C3D6A5C0CEAA1A0F368213" +
    	"C3D19843D0B4B09DCB9FC72D39C8DE41F1BF14D4BB4563CA" +
    	"28371621CAD3324B6A2D392145BEBFAC748805236F5CA2FE" +
    	"92B871CD8F9C36D3292B5509CA8CAA77A2ADFC7BFD77DDA6" +
    	"F71125A7456FEA153E433256A2261C6A06ED3693797E7995" +
    	"FAD5AABBCFBE3EDA2741E375404AE25B"
    
    const P107 = "6B"
    
    const LARGE_PRIME = "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" +
    	"29024E088A67CC74020BBEA63B139B22514A08798E3404DD" +
    	"EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" +
    	"E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" +
    	"EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" +
    	"C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" +
    	"83655D23DCA3AD961C62F356208552BB9ED529077096966D" +
    	"670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" +
    	"E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" +
    	"DE2BCBF6955817183995497CEA956AE515D2261898FA0510" +
    	"15728E5A8AACAA68FFFFFFFFFFFFFFFF"
    
    const NONBYTEALIGNED_PRIME = "E2EE983D031DC1DB6F1A7A67DF0E9A8E5561DB8E8D49413394C049B" +
    	"7A8ACCEDC298708F121951D9CF920EC5D146727AA4AE535B0922C688B55B3DD2AE" +
    	"DF6C01C94764DAB937935AA83BE36E67760713AB44A6337C20E7861575E745D31F" +
    	"8B9E9AD8412118C62A3E2E29DF46B0864D0C951C394A5CBBDC6ADC718DD2A3E041" +
    	"023DBB5AB23EBB4742DE9C1687B5B34FA48C3521632C4A530E8FFB1BC51DADDF45" +
    	"3B0B2717C2BC6669ED76B4BDD5C9FF558E88F26E5785302BEDBCA23EAC5ACE9209" +
    	"6EE8A60642FB61E8F3D24990B8CB12EE448EEF78E184C7242DD161C7738F32BF29" +
    	"A841698978825B4111B4BC3E1E198455095958333D776D8B2BEEED3A1A1A221A6E" +
    	"37E664A64B83981C46FFDDC1A45E3D5211AAF8BFBC072768C4F50D7D7803D2D4F2" +
    	"78DE8014A47323631D7E064DE81C0C6BFA43EF0E6998860F1390B5D3FEACAF1696" +
    	"015CB79C3F9C2D93D961120CD0E5F12CBB687EAB045241F96789C38E89D796138E" +
    	"6319BE62E35D87B1048CA28BE389B575E994DCA755471584A09EC723742DC35873" +
    	"847AEF49F66E43873"
    
    var p107 []byte
    var modp2048 []byte
    var modp4096 []byte
    var largePrime []byte
    var nonByteAlignedPrime []byte
    
    func TestMain(m *testing.M) {
    	nonByteAlignedPrime = large.NewIntFromString(NONBYTEALIGNED_PRIME, 16).Bytes()
    	largePrime = large.NewIntFromString(LARGE_PRIME, 16).Bytes()
    	p107 = large.NewIntFromString(P107, 16).Bytes()
    	modp2048 = large.NewIntFromString(MODP2048, 16).Bytes()
    	modp4096 = large.NewIntFromString(MODP4096, 16).Bytes()
    	os.Exit(m.Run())
    }
    
    // TestInGroup_Empty tests if empty slice is ever in the group
    func TestInGroup_Empty(t *testing.T) {
    	zero := []byte{}
    
    	//Note these test different code paths because of the slice len
    	if InGroup(zero, p107) {
    		t.Errorf("Empty slice is never in the group! Not even p107!")
    	}
    	if InGroup(zero, modp2048) {
    		t.Errorf("Empty slice is never in the group! Not even modp2048!")
    	}
    	if InGroup(zero, modp4096) {
    		t.Errorf("Empty slice is never in the group! Not even modp4096!")
    	}
    }
    
    // TestInGroup_0 tests if 0 is ever in the group
    func TestInGroup_0(t *testing.T) {
    	zero := []byte{0}
    
    	zeroLenP := make([]byte, len(p107))
    	if InGroup(zero, p107) || InGroup(zeroLenP, p107) {
    		t.Errorf("Zero is never in the group! Not even p107!")
    	}
    	zeroLenP = make([]byte, len(modp2048))
    	if InGroup(zero, modp2048) || InGroup(zeroLenP, modp2048) {
    		t.Errorf("Zero is never in the group! Not even modp2048!")
    	}
    	zeroLenP = make([]byte, len(modp4096))
    	if InGroup(zero, modp4096) || InGroup(zeroLenP, modp4096) {
    		t.Errorf("Zero is never in the group! Not even modp4096!")
    	}
    }
    
    // TestInGroup_P tests if the prime is ever in the group.
    func TestInGroup_P(t *testing.T) {
    	//Note these test different code paths because of the slice len
    	if InGroup(p107, p107) {
    		t.Errorf("p107 is never in the group for p107!")
    	}
    	if InGroup(modp2048, modp2048) {
    		t.Errorf("modp2048 is never in the group for modp2048!")
    	}
    	if InGroup(modp4096, modp4096) {
    		t.Errorf("modp4096 is never in the group for modp4096!")
    	}
    	if !InGroup(p107, modp2048) {
    		t.Errorf("p107 is always in the group for modp2048!")
    	}
    	if !InGroup(p107, modp4096) {
    		t.Errorf("p107 is always in the group for modp4096!")
    	}
    	if !InGroup(modp2048, modp4096) {
    		t.Errorf("modp2048 is always in the group for modp4096!")
    	}
    	if InGroup(modp2048, p107) {
    		t.Errorf("modp2048 is never in the group for p107!")
    	}
    	if InGroup(modp4096, p107) {
    		t.Errorf("modp4096 is never in the group for p107!")
    	}
    	if InGroup(modp4096, modp2048) {
    		t.Errorf("modp4096 is never in the group for modp2048!")
    	}
    }
    
    // TestInGroup_1 tests that 1 is always in the group.
    func TestInGroup_1(t *testing.T) {
    	one32 := []byte{0, 0, 0, 1}
    	one := []byte{1}
    
    	// one32 is not in p107 because it's 4 bytes (longer than 107)
    	if InGroup(one32, p107) {
    		t.Errorf("32bit 1 is never in the group for p107!")
    	}
    
    	if !InGroup(one, p107) {
    		t.Errorf("1 is always in the group for p107!")
    	}
    	if !InGroup(one32, modp2048) {
    		t.Errorf("1 is always in the group for modp2048!")
    	}
    	if !InGroup(one, modp2048) {
    		t.Errorf("1 is always in the group for modp2048!")
    	}
    	if !InGroup(one32, modp4096) {
    		t.Errorf("1 is always in the group for modp4096!")
    	}
    	if !InGroup(one, modp4096) {
    		t.Errorf("1 is always in the group for modp4096!")
    	}
    }
    
    // TestInGroupPsub1 tests that P - 1 is in the group
    func TestInGroup_Psub1(t *testing.T) {
    	one := large.NewInt(1)
    
    	p107sub1 := large.NewInt(0)
    	p107sub1.Sub(large.NewIntFromString(P107, 16), one)
    
    	p2048sub1 := large.NewInt(0)
    	p2048sub1.Sub(large.NewIntFromString(MODP2048, 16), one)
    
    	p4096sub1 := large.NewInt(0)
    	p4096sub1.Sub(large.NewIntFromString(MODP4096, 16), one)
    
    	if !InGroup(p107sub1.Bytes(), p107) {
    		t.Errorf("p107sub1 is always in group for p107!")
    	}
    	if !InGroup(p2048sub1.Bytes(), modp2048) {
    		t.Errorf("p2048sub1 is always in group for modp2048!")
    	}
    	if !InGroup(p4096sub1.Bytes(), modp4096) {
    		t.Errorf("p4096sub1 is always in group for modp4096!")
    	}
    }
    
    // TestInGroupPplus1 tests that P + 1 is not in the group
    func TestInGroup_Pplus1(t *testing.T) {
    	one := large.NewInt(1)
    
    	p107plus1 := large.NewInt(0)
    	p107plus1.Add(large.NewIntFromString(P107, 16), one)
    
    	p2048plus1 := large.NewInt(0)
    	p2048plus1.Add(large.NewIntFromString(MODP2048, 16), one)
    
    	p4096plus1 := large.NewInt(0)
    	p4096plus1.Add(large.NewIntFromString(MODP4096, 16), one)
    
    	if InGroup(p107plus1.Bytes(), p107) {
    		t.Errorf("p107plus1 is never in group for p107!")
    	}
    	if InGroup(p2048plus1.Bytes(), modp2048) {
    		t.Errorf("p2048plus1 is never in group for modp2048!")
    	}
    	if InGroup(p4096plus1.Bytes(), modp4096) {
    		t.Errorf("p4096plus1 is never in group for modp4096!")
    	}
    }
    
    // TestGenerateInGroup_LargeSize tests that GenerateInGroup
    // eventually generates a number in the small group
    func TestGenerateInGroup_LargeSize(t *testing.T) {
    	rng := NewSystemRNG()
    
    	timeout := time.After(3 * time.Second)
    	done := make(chan bool)
    	go func() {
    		// do your testing
    		b, err := GenerateInGroup(p107, 32, rng)
    		if err != nil {
    			t.Errorf("%v", err)
    		}
    		if !InGroup(b, p107) {
    			t.Errorf("b not in p107: %v", b)
    		}
    		done <- true
    	}()
    
    	select {
    	case <-timeout:
    		t.Fatal("GenerateInGroup took too long to complete!")
    	case <-done:
    	}
    }
    
    //Happy path with a large, byte aligned path
    func TestGenerate(t *testing.T) {
    	rng := NewSystemRNG()
    
    	b, err := GenerateInGroup(largePrime, len(largePrime), rng)
    	if err != nil {
    		t.Errorf("%v", err)
    	}
    	if !InGroup(b, largePrime) {
    		t.Errorf("b not in largePrime: %v", b)
    	}
    	if len(b) != len(largePrime) {
    		t.Errorf("Failed to generate a value of same length of prime! "+
    			"Expected %v bytes, generated %v bytes", len(largePrime), len(b))
    	}
    
    }
    
    //Happy path with a non byte aligned prime
    func TestGenerate_Padding(t *testing.T) {
    	rng := NewSystemRNG()
    
    	b, err := GenerateInGroup(nonByteAlignedPrime, len(nonByteAlignedPrime), rng)
    	if err != nil {
    		t.Errorf("%v", err)
    	}
    	if !InGroup(b, nonByteAlignedPrime) {
    		t.Errorf("b not in largePrime: %v", b)
    	}
    	if len(b) != len(nonByteAlignedPrime) {
    		t.Errorf("Failed to generate a value of same length of prime! "+
    			"Expected %v bytes, generated %v bytes", len(nonByteAlignedPrime), len(b))
    	}
    }
    
    // Generate aes.BlockSize 0's first
    type ZeroRNG struct {
    	Count int
    }
    
    func (z *ZeroRNG) Read(b []byte) (int, error) {
    	numBytes := len(b)
    	i := 0
    	for z.Count != 0 && numBytes != 0 {
    		numBytes--
    		z.Count--
    		b[i] = 0
    		i++
    	}
    	if numBytes > 0 {
    		rng := NewSystemRNG()
    		c, _ := rng.Read(b[i:numBytes])
    		i += c
    	}
    	return i, nil
    }
    func (z *ZeroRNG) SetSeed(seed []byte) {
    	z.Count = int(seed[0])
    }
    func TestGenerate_ZeroStart(t *testing.T) {
    	rng := &ZeroRNG{Count: aes.BlockSize}
    
    	b, err := GenerateInGroup(largePrime, len(largePrime), rng)
    	if err != nil {
    		t.Errorf("%v", err)
    	}
    	if !InGroup(b, largePrime) {
    		t.Errorf("b not in largePrime: %v", b)
    	}
    	if len(b) != len(largePrime) {
    		t.Errorf("Failed to generate a value of same length of prime! "+
    			"Expected %v bytes, generated %v bytes", len(largePrime), len(b))
    	}
    	for i := 0; i < aes.BlockSize; i++ {
    		if b[i] != 0 {
    			t.Errorf("All bytes should be 0, byte %d is %d", i, b[i])
    		}
    	}
    }