github.com/coyove/sdss@v0.0.0-20231129015646-c2ec58cca6a2/contrib/skip32/skip32.go (about)

     1  // Copyright (c) 2012 Damian Gryski <damian@gryski.com>
     2  // Licensed under MIT
     3  
     4  // Package skip32 implements the Skip32 blockcipher
     5  /*
     6  SKIP32 is a 32-bit block cipher based on SKIPJACK, written by Greg Rose of QUALCOMM Australia.
     7  It is useful for obfuscating small integers (like sequential database ids)
     8  that are exposed to prevent an analysis of growth rates as in:
     9  https://en.wikipedia.org/wiki/German_tank_problem
    10  This library deliberately exposes only the integer obfuscation routines and
    11  hides the low-level encryption.
    12  Using this routine to hide IDs is not sufficient security by itself.  Please
    13  ensure your application does secondary validation and do not rely on the
    14  secrecy of the generated IDs.
    15  */
    16  package skip32
    17  
    18  import (
    19  	"unsafe"
    20  )
    21  
    22  var ftable = [...]byte{
    23  	0xa3, 0xd7, 0x09, 0x83, 0xf8, 0x48, 0xf6, 0xf4, 0xb3, 0x21, 0x15, 0x78, 0x99, 0xb1, 0xaf, 0xf9,
    24  	0xe7, 0x2d, 0x4d, 0x8a, 0xce, 0x4c, 0xca, 0x2e, 0x52, 0x95, 0xd9, 0x1e, 0x4e, 0x38, 0x44, 0x28,
    25  	0x0a, 0xdf, 0x02, 0xa0, 0x17, 0xf1, 0x60, 0x68, 0x12, 0xb7, 0x7a, 0xc3, 0xe9, 0xfa, 0x3d, 0x53,
    26  	0x96, 0x84, 0x6b, 0xba, 0xf2, 0x63, 0x9a, 0x19, 0x7c, 0xae, 0xe5, 0xf5, 0xf7, 0x16, 0x6a, 0xa2,
    27  	0x39, 0xb6, 0x7b, 0x0f, 0xc1, 0x93, 0x81, 0x1b, 0xee, 0xb4, 0x1a, 0xea, 0xd0, 0x91, 0x2f, 0xb8,
    28  	0x55, 0xb9, 0xda, 0x85, 0x3f, 0x41, 0xbf, 0xe0, 0x5a, 0x58, 0x80, 0x5f, 0x66, 0x0b, 0xd8, 0x90,
    29  	0x35, 0xd5, 0xc0, 0xa7, 0x33, 0x06, 0x65, 0x69, 0x45, 0x00, 0x94, 0x56, 0x6d, 0x98, 0x9b, 0x76,
    30  	0x97, 0xfc, 0xb2, 0xc2, 0xb0, 0xfe, 0xdb, 0x20, 0xe1, 0xeb, 0xd6, 0xe4, 0xdd, 0x47, 0x4a, 0x1d,
    31  	0x42, 0xed, 0x9e, 0x6e, 0x49, 0x3c, 0xcd, 0x43, 0x27, 0xd2, 0x07, 0xd4, 0xde, 0xc7, 0x67, 0x18,
    32  	0x89, 0xcb, 0x30, 0x1f, 0x8d, 0xc6, 0x8f, 0xaa, 0xc8, 0x74, 0xdc, 0xc9, 0x5d, 0x5c, 0x31, 0xa4,
    33  	0x70, 0x88, 0x61, 0x2c, 0x9f, 0x0d, 0x2b, 0x87, 0x50, 0x82, 0x54, 0x64, 0x26, 0x7d, 0x03, 0x40,
    34  	0x34, 0x4b, 0x1c, 0x73, 0xd1, 0xc4, 0xfd, 0x3b, 0xcc, 0xfb, 0x7f, 0xab, 0xe6, 0x3e, 0x5b, 0xa5,
    35  	0xad, 0x04, 0x23, 0x9c, 0x14, 0x51, 0x22, 0xf0, 0x29, 0x79, 0x71, 0x7e, 0xff, 0x8c, 0x0e, 0xe2,
    36  	0x0c, 0xef, 0xbc, 0x72, 0x75, 0x6f, 0x37, 0xa1, 0xec, 0xd3, 0x8e, 0x62, 0x8b, 0x86, 0x10, 0xe8,
    37  	0x08, 0x77, 0x11, 0xbe, 0x92, 0x4f, 0x24, 0xc5, 0x32, 0x36, 0x9d, 0xcf, 0xf3, 0xa6, 0xbb, 0xac,
    38  	0x5e, 0x6c, 0xa9, 0x13, 0x57, 0x25, 0xb5, 0xe3, 0xbd, 0xa8, 0x3a, 0x01, 0x05, 0x59, 0x2a, 0x46,
    39  }
    40  
    41  func g(key [10]byte, k int, w uint16) uint16 {
    42  
    43  	g1 := byte((w >> 8) & 0xff)
    44  	g2 := byte(w & 0xff)
    45  
    46  	g3 := ftable[g2^key[(4*k+0)%10]] ^ g1
    47  	g4 := ftable[g3^key[(4*k+1)%10]] ^ g2
    48  	g5 := ftable[g4^key[(4*k+2)%10]] ^ g3
    49  	g6 := ftable[g5^key[(4*k+3)%10]] ^ g4
    50  
    51  	return (uint16(g5) << 8) + uint16(g6)
    52  }
    53  
    54  func crypt32(key [10]byte, buf uint32, encrypt bool) uint32 {
    55  	var kstep, k int
    56  
    57  	if encrypt {
    58  		kstep = 1
    59  		k = 0
    60  	} else {
    61  		kstep = -1
    62  		k = 23
    63  	}
    64  
    65  	/* pack into words */
    66  	wl := uint16(buf >> 16)
    67  	wr := uint16(buf)
    68  
    69  	/* 24 feistel rounds, doubled up */
    70  	for i := 0; i < 24/2; i++ {
    71  		wr ^= g(key, k, wl) ^ uint16(k)
    72  		k += kstep
    73  		wl ^= g(key, k, wr) ^ uint16(k)
    74  		k += kstep
    75  	}
    76  
    77  	/* implicitly swap halves while unpacking */
    78  	return uint32(byte(wr>>8))<<24 |
    79  		uint32(byte(wr&0xFF))<<16 |
    80  		uint32(byte(wl>>8))<<8 |
    81  		uint32(byte(wl&0xFF))
    82  }
    83  
    84  // Skip32 is a 32-bit integer obfuscator
    85  type Skip32 [10]byte
    86  
    87  func (s Skip32) Encrypt(id uint32) uint32 {
    88  	return crypt32(s, id, true /* encrypt */)
    89  }
    90  
    91  func (s Skip32) EncryptBytes(buf []byte) {
    92  	id := (*uint32)(unsafe.Pointer(&buf[0]))
    93  	*id = crypt32(s, *id, true /* encrypt */)
    94  }
    95  
    96  func (s Skip32) Decrypt(id uint32) uint32 {
    97  	return crypt32(s, id, false /* decrypt */)
    98  }
    99  
   100  func (s Skip32) DecryptBytes(buf []byte) {
   101  	id := (*uint32)(unsafe.Pointer(&buf[0]))
   102  	*id = crypt32(s, *id, false)
   103  }
   104  
   105  func ReadSkip32Key(v string) (s Skip32) {
   106  	copy(s[:], v)
   107  	return
   108  }