/model/account/credentials_test.go

https://github.com/cozy/cozy-stack · Go · 236 lines · 214 code · 22 blank · 0 comment · 39 complexity · c5da6881a5df914cd0beee0a275e996c MD5 · raw file

  1. package account
  2. import (
  3. "bytes"
  4. cryptorand "crypto/rand"
  5. "encoding/base64"
  6. "encoding/json"
  7. "io"
  8. "math/rand"
  9. "os"
  10. "testing"
  11. "time"
  12. "github.com/cozy/cozy-stack/pkg/config/config"
  13. "github.com/cozy/cozy-stack/pkg/crypto"
  14. "github.com/cozy/cozy-stack/pkg/utils"
  15. "github.com/stretchr/testify/assert"
  16. )
  17. func TestEncryptDecrytCredentials(t *testing.T) {
  18. encryptedCreds1, err := EncryptCredentials("me@mycozy.cloud", "fzEE6HFWsSp8jP")
  19. if !assert.NoError(t, err) {
  20. return
  21. }
  22. encryptedCreds2, err := EncryptCredentials("me@mycozy.cloud", "fzEE6HFWsSp8jP")
  23. if !assert.NoError(t, err) {
  24. return
  25. }
  26. encryptedCreds3, err := EncryptCredentials("", "fzEE6HFWsSp8jP")
  27. if !assert.NoError(t, err) {
  28. return
  29. }
  30. assert.NotEqual(t, encryptedCreds1, encryptedCreds2)
  31. {
  32. login, password, err := DecryptCredentials(encryptedCreds1)
  33. if !assert.NoError(t, err) {
  34. return
  35. }
  36. assert.Equal(t, "me@mycozy.cloud", login)
  37. assert.Equal(t, "fzEE6HFWsSp8jP", password)
  38. }
  39. {
  40. login, password, err := DecryptCredentials(encryptedCreds2)
  41. if !assert.NoError(t, err) {
  42. return
  43. }
  44. assert.Equal(t, "me@mycozy.cloud", login)
  45. assert.Equal(t, "fzEE6HFWsSp8jP", password)
  46. }
  47. {
  48. login, password, err := DecryptCredentials(encryptedCreds3)
  49. if !assert.NoError(t, err) {
  50. return
  51. }
  52. assert.Equal(t, "", login)
  53. assert.Equal(t, "fzEE6HFWsSp8jP", password)
  54. }
  55. }
  56. func TestEncryptDecrytUTF8Credentials(t *testing.T) {
  57. rng := rand.New(rand.NewSource(time.Now().UnixNano()))
  58. for i := 0; i < 1024; i++ {
  59. login := string(crypto.GenerateRandomBytes(rng.Intn(256)))
  60. password := string(crypto.GenerateRandomBytes(rng.Intn(256)))
  61. encryptedCreds, err := EncryptCredentials(login, password)
  62. if !assert.NoError(t, err) {
  63. return
  64. }
  65. loginDec, passwordDec, err := DecryptCredentials(encryptedCreds)
  66. if !assert.NoError(t, err) {
  67. return
  68. }
  69. assert.Equal(t, loginDec, login)
  70. assert.Equal(t, passwordDec, password)
  71. }
  72. for i := 0; i < 1024; i++ {
  73. login := utils.RandomString(rng.Intn(256))
  74. password := utils.RandomString(rng.Intn(256))
  75. encryptedCreds, err := EncryptCredentials(login, password)
  76. if !assert.NoError(t, err) {
  77. return
  78. }
  79. loginDec, passwordDec, err := DecryptCredentials(encryptedCreds)
  80. if !assert.NoError(t, err) {
  81. return
  82. }
  83. assert.Equal(t, loginDec, login)
  84. assert.Equal(t, passwordDec, password)
  85. }
  86. }
  87. func TestDecryptCredentialsRandom(t *testing.T) {
  88. rng := rand.New(rand.NewSource(time.Now().UnixNano()))
  89. for i := 0; i < 1024; i++ {
  90. encrypted := base64.StdEncoding.EncodeToString(crypto.GenerateRandomBytes(rng.Intn(256)))
  91. _, _, err := DecryptCredentials(encrypted)
  92. assert.Error(t, err)
  93. }
  94. for i := 0; i < 1024; i++ {
  95. encrypted := crypto.GenerateRandomBytes(rng.Intn(256))
  96. encryptedWithHeader := make([]byte, len(cipherHeader)+len(encrypted))
  97. copy(encryptedWithHeader[0:], cipherHeader)
  98. copy(encryptedWithHeader[len(cipherHeader):], encrypted)
  99. _, _, err := DecryptCredentials(base64.StdEncoding.EncodeToString(encryptedWithHeader))
  100. assert.Error(t, err)
  101. }
  102. }
  103. func TestRandomBitFlipsCredentials(t *testing.T) {
  104. original, err := EncryptCredentials("toto@titi.com", "X3hVYLJLRiUyCs")
  105. if !assert.NoError(t, err) {
  106. return
  107. }
  108. originalBuffer, err := base64.StdEncoding.DecodeString(original)
  109. if !assert.NoError(t, err) {
  110. return
  111. }
  112. flipped := make([]byte, len(originalBuffer))
  113. copy(flipped, originalBuffer)
  114. login, passwd, err := DecryptCredentials(base64.StdEncoding.EncodeToString(flipped))
  115. if !assert.NoError(t, err) {
  116. return
  117. }
  118. assert.Equal(t, "toto@titi.com", login)
  119. assert.Equal(t, "X3hVYLJLRiUyCs", passwd)
  120. rng := rand.New(rand.NewSource(time.Now().UnixNano()))
  121. for i := 0; i < 1000; i++ {
  122. copy(flipped, originalBuffer)
  123. flipsLen := rng.Intn(30) + 1
  124. flipsSet := make([]int, 0, flipsLen)
  125. for len(flipsSet) < flipsLen {
  126. flipValue := rng.Intn(len(originalBuffer) * 8)
  127. flipFound := false
  128. for j := 0; j < len(flipsSet); j++ {
  129. if flipsSet[j] == flipValue {
  130. flipFound = true
  131. break
  132. }
  133. }
  134. if !flipFound {
  135. flipsSet = append(flipsSet, flipValue)
  136. }
  137. }
  138. for _, flipValue := range flipsSet {
  139. mask := byte(0x1 << uint(flipValue%8))
  140. flipped[flipValue/8] ^= mask
  141. }
  142. _, _, err := DecryptCredentials(base64.StdEncoding.EncodeToString(flipped))
  143. if !assert.Error(t, err) {
  144. t.Fatalf("Failed with flips %v", flipsSet)
  145. return
  146. }
  147. }
  148. }
  149. func TestEncryptDecryptData(t *testing.T) {
  150. var data interface{}
  151. err := json.Unmarshal([]byte(`{"foo":"bar","baz":{"quz": "quuz"}}`), &data)
  152. if !assert.NoError(t, err) {
  153. return
  154. }
  155. encBuffer, err := EncryptCredentialsData(data)
  156. if !assert.NoError(t, err) {
  157. return
  158. }
  159. decData, err := DecryptCredentialsData(encBuffer)
  160. if !assert.NoError(t, err) {
  161. return
  162. }
  163. assert.EqualValues(t, data, decData)
  164. }
  165. func TestRandomBitFlipsBuffer(t *testing.T) {
  166. plainBuffer := make([]byte, 256)
  167. _, err := io.ReadFull(cryptorand.Reader, plainBuffer)
  168. if !assert.NoError(t, err) {
  169. return
  170. }
  171. original, err := EncryptBufferWithKey(config.GetVault().CredentialsEncryptorKey(), plainBuffer)
  172. if !assert.NoError(t, err) {
  173. return
  174. }
  175. flipped := make([]byte, len(original))
  176. copy(flipped, original)
  177. testBuffer, err := DecryptBufferWithKey(config.GetVault().CredentialsDecryptorKey(), flipped)
  178. if !assert.NoError(t, err) {
  179. return
  180. }
  181. assert.True(t, bytes.Equal(plainBuffer, testBuffer))
  182. rng := rand.New(rand.NewSource(time.Now().UnixNano()))
  183. for i := 0; i < 1000; i++ {
  184. copy(flipped, original)
  185. flipsLen := rng.Intn(30) + 1
  186. flipsSet := make([]int, 0, flipsLen)
  187. for len(flipsSet) < flipsLen {
  188. flipValue := rng.Intn(len(original) * 8)
  189. flipFound := false
  190. for j := 0; j < len(flipsSet); j++ {
  191. if flipsSet[j] == flipValue {
  192. flipFound = true
  193. break
  194. }
  195. }
  196. if !flipFound {
  197. flipsSet = append(flipsSet, flipValue)
  198. }
  199. }
  200. for _, flipValue := range flipsSet {
  201. mask := byte(0x1 << uint(flipValue%8))
  202. flipped[flipValue/8] ^= mask
  203. }
  204. _, err := DecryptBufferWithKey(config.GetVault().CredentialsDecryptorKey(), flipped)
  205. if !assert.Error(t, err) {
  206. t.Fatalf("Failed with flips %v", flipsSet)
  207. return
  208. }
  209. }
  210. }
  211. func TestMain(m *testing.M) {
  212. config.UseTestFile()
  213. os.Exit(m.Run())
  214. }