You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

243 lines
6.5 KiB

  1. package cryptostore_test
  2. import (
  3. "testing"
  4. "github.com/stretchr/testify/assert"
  5. "github.com/stretchr/testify/require"
  6. crypto "github.com/tendermint/go-crypto"
  7. "github.com/tendermint/go-keys/cryptostore"
  8. "github.com/tendermint/go-keys/storage/memstorage"
  9. )
  10. // TestKeyManagement makes sure we can manipulate these keys well
  11. func TestKeyManagement(t *testing.T) {
  12. assert, require := assert.New(t), require.New(t)
  13. // make the storage with reasonable defaults
  14. cstore := cryptostore.New(
  15. cryptostore.SecretBox,
  16. memstorage.New(),
  17. )
  18. algo := crypto.NameEd25519
  19. n1, n2, n3 := "personal", "business", "other"
  20. p1, p2 := "1234", "really-secure!@#$"
  21. // Check empty state
  22. l, err := cstore.List()
  23. require.Nil(err)
  24. assert.Empty(l)
  25. // create some keys
  26. _, err = cstore.Get(n1)
  27. assert.NotNil(err)
  28. i, err := cstore.Create(n1, p1, algo)
  29. require.Equal(n1, i.Name)
  30. require.Nil(err)
  31. _, err = cstore.Create(n2, p2, algo)
  32. require.Nil(err)
  33. // we can get these keys
  34. i2, err := cstore.Get(n2)
  35. assert.Nil(err)
  36. _, err = cstore.Get(n3)
  37. assert.NotNil(err)
  38. // list shows them in order
  39. keys, err := cstore.List()
  40. require.Nil(err)
  41. require.Equal(2, len(keys))
  42. // note these are in alphabetical order
  43. assert.Equal(n2, keys[0].Name)
  44. assert.Equal(n1, keys[1].Name)
  45. assert.Equal(i2.PubKey, keys[0].PubKey)
  46. // deleting a key removes it
  47. err = cstore.Delete("bad name", "foo")
  48. require.NotNil(err)
  49. err = cstore.Delete(n1, p1)
  50. require.Nil(err)
  51. keys, err = cstore.List()
  52. require.Nil(err)
  53. assert.Equal(1, len(keys))
  54. _, err = cstore.Get(n1)
  55. assert.NotNil(err)
  56. // make sure that it only signs with the right password
  57. // tx := mock.NewSig([]byte("mytransactiondata"))
  58. // err = cstore.Sign(n2, p1, tx)
  59. // assert.NotNil(err)
  60. // err = cstore.Sign(n2, p2, tx)
  61. // assert.Nil(err, "%+v", err)
  62. // sigs, err := tx.Signers()
  63. // assert.Nil(err, "%+v", err)
  64. // if assert.Equal(1, len(sigs)) {
  65. // assert.Equal(i2.PubKey, sigs[0])
  66. // }
  67. }
  68. // TestSignVerify does some detailed checks on how we sign and validate
  69. // signatures
  70. // func TestSignVerify(t *testing.T) {
  71. // assert, require := assert.New(t), require.New(t)
  72. // // make the storage with reasonable defaults
  73. // cstore := cryptostore.New(
  74. // cryptostore.GenSecp256k1,
  75. // cryptostore.SecretBox,
  76. // memstorage.New(),
  77. // )
  78. // n1, n2 := "some dude", "a dudette"
  79. // p1, p2 := "1234", "foobar"
  80. // // create two users and get their info
  81. // err := cstore.Create(n1, p1)
  82. // require.Nil(err)
  83. // i1, err := cstore.Get(n1)
  84. // require.Nil(err)
  85. // err = cstore.Create(n2, p2)
  86. // require.Nil(err)
  87. // i2, err := cstore.Get(n2)
  88. // require.Nil(err)
  89. // // let's try to sign some messages
  90. // d1 := []byte("my first message")
  91. // d2 := []byte("some other important info!")
  92. // // try signing both data with both keys...
  93. // s11, err := cstore.Signature(n1, p1, d1)
  94. // require.Nil(err)
  95. // s12, err := cstore.Signature(n1, p1, d2)
  96. // require.Nil(err)
  97. // s21, err := cstore.Signature(n2, p2, d1)
  98. // require.Nil(err)
  99. // s22, err := cstore.Signature(n2, p2, d2)
  100. // require.Nil(err)
  101. // // let's try to validate and make sure it only works when everything is proper
  102. // keys := [][]byte{i1.PubKey, i2.PubKey}
  103. // data := [][]byte{d1, d2}
  104. // sigs := [][]byte{s11, s12, s21, s22}
  105. // // loop over keys and data
  106. // for k := 0; k < 2; k++ {
  107. // for d := 0; d < 2; d++ {
  108. // // make sure only the proper sig works
  109. // good := 2*k + d
  110. // for s := 0; s < 4; s++ {
  111. // err = cstore.Verify(data[d], sigs[s], keys[k])
  112. // if s == good {
  113. // assert.Nil(err, "%+v", err)
  114. // } else {
  115. // assert.NotNil(err)
  116. // }
  117. // }
  118. // }
  119. // }
  120. // }
  121. func assertPassword(assert *assert.Assertions, cstore cryptostore.Manager, name, pass, badpass string) {
  122. err := cstore.Update(name, badpass, pass)
  123. assert.NotNil(err)
  124. err = cstore.Update(name, pass, pass)
  125. assert.Nil(err, "%+v", err)
  126. }
  127. // TestAdvancedKeyManagement verifies update, import, export functionality
  128. func TestAdvancedKeyManagement(t *testing.T) {
  129. assert, require := assert.New(t), require.New(t)
  130. // make the storage with reasonable defaults
  131. cstore := cryptostore.New(
  132. cryptostore.SecretBox,
  133. memstorage.New(),
  134. )
  135. algo := crypto.NameSecp256k1
  136. n1, n2 := "old-name", "new name"
  137. p1, p2, p3, pt := "1234", "foobar", "ding booms!", "really-secure!@#$"
  138. // make sure key works with initial password
  139. _, err := cstore.Create(n1, p1, algo)
  140. require.Nil(err, "%+v", err)
  141. assertPassword(assert, cstore, n1, p1, p2)
  142. // update password requires the existing password
  143. err = cstore.Update(n1, "jkkgkg", p2)
  144. assert.NotNil(err)
  145. assertPassword(assert, cstore, n1, p1, p2)
  146. // then it changes the password when correct
  147. err = cstore.Update(n1, p1, p2)
  148. assert.Nil(err)
  149. // p2 is now the proper one!
  150. assertPassword(assert, cstore, n1, p2, p1)
  151. // exporting requires the proper name and passphrase
  152. _, err = cstore.Export(n2, p2, pt)
  153. assert.NotNil(err)
  154. _, err = cstore.Export(n1, p1, pt)
  155. assert.NotNil(err)
  156. exported, err := cstore.Export(n1, p2, pt)
  157. require.Nil(err, "%+v", err)
  158. // import fails on bad transfer pass
  159. err = cstore.Import(n2, p3, p2, exported)
  160. assert.NotNil(err)
  161. // import cannot overwrite existing keys
  162. err = cstore.Import(n1, p3, pt, exported)
  163. assert.NotNil(err)
  164. // we can now import under another name
  165. err = cstore.Import(n2, p3, pt, exported)
  166. require.Nil(err, "%+v", err)
  167. // make sure both passwords are now properly set (not to the transfer pass)
  168. assertPassword(assert, cstore, n1, p2, pt)
  169. assertPassword(assert, cstore, n2, p3, pt)
  170. }
  171. // func ExampleStore() {
  172. // // Select the encryption and storage for your cryptostore
  173. // cstore := cryptostore.New(
  174. // cryptostore.GenEd25519,
  175. // cryptostore.SecretBox,
  176. // // Note: use filestorage.New(dir) for real data
  177. // memstorage.New(),
  178. // )
  179. // // Add keys and see they return in alphabetical order
  180. // cstore.Create("Bob", "friend")
  181. // cstore.Create("Alice", "secret")
  182. // cstore.Create("Carl", "mitm")
  183. // info, _ := cstore.List()
  184. // for _, i := range info {
  185. // fmt.Println(i.Name)
  186. // }
  187. // // We need to use passphrase to generate a signature
  188. // tx := mock.NewSig([]byte("deadbeef"))
  189. // err := cstore.Sign("Bob", "friend", tx)
  190. // if err != nil {
  191. // fmt.Println("don't accept real passphrase")
  192. // }
  193. // // and we can validate the signature with publically available info
  194. // binfo, _ := cstore.Get("Bob")
  195. // sigs, err := tx.Signers()
  196. // if err != nil {
  197. // fmt.Println("badly signed")
  198. // } else if bytes.Equal(sigs[0].Bytes(), binfo.PubKey.Bytes()) {
  199. // fmt.Println("signed by Bob")
  200. // } else {
  201. // fmt.Println("signed by someone else")
  202. // }
  203. // // Output:
  204. // // Alice
  205. // // Bob
  206. // // Carl
  207. // // signed by Bob
  208. // }