wechat_pay_cipher_test.go 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353
  1. // Copyright 2021 Tencent Inc. All rights reserved.
  2. package ciphers
  3. import (
  4. "context"
  5. "github.com/agiledragon/gomonkey"
  6. "reflect"
  7. "testing"
  8. "github.com/stretchr/testify/assert"
  9. "github.com/stretchr/testify/require"
  10. "github.com/wechatpay-apiv3/wechatpay-go/core"
  11. "github.com/wechatpay-apiv3/wechatpay-go/core/cipher/decryptors"
  12. "github.com/wechatpay-apiv3/wechatpay-go/core/cipher/encryptors"
  13. )
  14. type Student struct {
  15. Name string `encryption:"EM_APIV3"`
  16. Age int
  17. Addresses []Address
  18. Parents *[]Parent
  19. // unexported secret
  20. secret string `encryption:"EM_APIV3"`
  21. IDs []int
  22. }
  23. type Address struct {
  24. // No Tag
  25. Country *string
  26. // Not EM_APIV3 encryption Tag
  27. Province *string `encryption:"EM_APIV2"`
  28. // EM_APIV3 encryption Tag
  29. City **string `encryption:"EM_APIV3"`
  30. Street *string `encryption:"EM_APIV3"`
  31. }
  32. type Parent struct {
  33. Name string `encryption:"EM_APIV3"`
  34. PhoneNumber *string `encryption:"EM_APIV3"`
  35. }
  36. func TestContextKey_String(t *testing.T) {
  37. assert.Equal(t, "WPCipherContext(EncryptSerial)", contextKeyEncryptSerial.String())
  38. }
  39. func TestWechatPayCipher_Encrypt_Decrypt(t *testing.T) {
  40. cityCD := core.String("成都")
  41. cityLA := core.String("LA")
  42. s := Student{
  43. Name: "小可",
  44. Age: 8,
  45. Addresses: []Address{
  46. {
  47. Country: core.String("中国"),
  48. Province: core.String("四川"),
  49. City: &cityCD,
  50. Street: core.String("春熙路"),
  51. },
  52. {
  53. Country: core.String("USA"),
  54. Province: core.String("California"),
  55. City: &cityLA,
  56. Street: core.String("Nowhere"),
  57. },
  58. },
  59. Parents: &[]Parent{
  60. {
  61. Name: "爸",
  62. PhoneNumber: core.String("13000000000"),
  63. },
  64. {
  65. Name: "妈",
  66. PhoneNumber: nil,
  67. },
  68. },
  69. secret: "this is secret",
  70. IDs: []int{
  71. 12345,
  72. 54321,
  73. },
  74. }
  75. c := WechatPayCipher{
  76. encryptor: &encryptors.MockEncryptor{
  77. Serial: "Mock Serial",
  78. },
  79. decryptor: &decryptors.MockDecryptor{},
  80. }
  81. serial, err := c.Encrypt(context.Background(), &s)
  82. assert.Equal(t, "Mock Serial", serial)
  83. require.NoError(t, err)
  84. assert.Equal(t, "Encrypted小可", s.Name)
  85. assert.Equal(t, 8, s.Age)
  86. assert.Equal(t, "中国", *(s.Addresses[0].Country))
  87. assert.Equal(t, "四川", *(s.Addresses[0].Province))
  88. assert.Equal(t, "Encrypted成都", **(s.Addresses[0].City))
  89. assert.Equal(t, "Encrypted春熙路", *(s.Addresses[0].Street))
  90. assert.Equal(t, "USA", *(s.Addresses[1].Country))
  91. assert.Equal(t, "California", *(s.Addresses[1].Province))
  92. assert.Equal(t, "EncryptedLA", **(s.Addresses[1].City))
  93. assert.Equal(t, "EncryptedNowhere", *(s.Addresses[1].Street))
  94. assert.Equal(t, "Encrypted爸", (*s.Parents)[0].Name)
  95. assert.Equal(t, "Encrypted13000000000", *((*s.Parents)[0].PhoneNumber))
  96. assert.Equal(t, "Encrypted妈", (*s.Parents)[1].Name)
  97. assert.Equal(t, (*string)(nil), (*s.Parents)[1].PhoneNumber)
  98. assert.Equal(t, "this is secret", s.secret) // unexported fields will be skipped
  99. assert.Equal(t, 12345, s.IDs[0])
  100. assert.Equal(t, 54321, s.IDs[1])
  101. err = c.Decrypt(context.Background(), &s)
  102. require.NoError(t, err)
  103. assert.Equal(t, "小可", s.Name)
  104. assert.Equal(t, 8, s.Age)
  105. assert.Equal(t, "中国", *(s.Addresses[0].Country))
  106. assert.Equal(t, "四川", *(s.Addresses[0].Province))
  107. assert.Equal(t, "成都", **(s.Addresses[0].City))
  108. assert.Equal(t, "春熙路", *(s.Addresses[0].Street))
  109. assert.Equal(t, "USA", *(s.Addresses[1].Country))
  110. assert.Equal(t, "California", *(s.Addresses[1].Province))
  111. assert.Equal(t, "LA", **(s.Addresses[1].City))
  112. assert.Equal(t, "Nowhere", *(s.Addresses[1].Street))
  113. assert.Equal(t, "爸", (*s.Parents)[0].Name)
  114. assert.Equal(t, "13000000000", *((*s.Parents)[0].PhoneNumber))
  115. assert.Equal(t, "妈", (*s.Parents)[1].Name)
  116. assert.Equal(t, (*string)(nil), (*s.Parents)[1].PhoneNumber)
  117. assert.Equal(t, "this is secret", s.secret) // unexported fields will be skipped
  118. assert.Equal(t, 12345, s.IDs[0])
  119. assert.Equal(t, 54321, s.IDs[1])
  120. }
  121. func TestWechatPayCipher_Encrypt_DecryptWithValue(t *testing.T) {
  122. cityCD := core.String("成都")
  123. cityLA := core.String("LA")
  124. s := Student{
  125. Name: "小可",
  126. Age: 8,
  127. Addresses: []Address{
  128. {
  129. Country: core.String("中国"),
  130. Province: core.String("四川"),
  131. City: &cityCD,
  132. Street: core.String("春熙路"),
  133. },
  134. {
  135. Country: core.String("USA"),
  136. Province: core.String("California"),
  137. City: &cityLA,
  138. Street: core.String("Nowhere"),
  139. },
  140. },
  141. Parents: &[]Parent{
  142. {
  143. Name: "爸",
  144. PhoneNumber: core.String("13000000000"),
  145. },
  146. {
  147. Name: "妈",
  148. PhoneNumber: nil,
  149. },
  150. },
  151. }
  152. c := NewWechatPayCipher(
  153. &encryptors.MockEncryptor{
  154. Serial: "Mock Serial",
  155. },
  156. &decryptors.MockDecryptor{},
  157. )
  158. serial, err := c.Encrypt(context.Background(), reflect.ValueOf(&s))
  159. assert.Equal(t, "Mock Serial", serial)
  160. require.NoError(t, err)
  161. assert.Equal(t, "Encrypted小可", s.Name)
  162. assert.Equal(t, 8, s.Age)
  163. assert.Equal(t, "中国", *(s.Addresses[0].Country))
  164. assert.Equal(t, "四川", *(s.Addresses[0].Province))
  165. assert.Equal(t, "Encrypted成都", **(s.Addresses[0].City))
  166. assert.Equal(t, "Encrypted春熙路", *(s.Addresses[0].Street))
  167. assert.Equal(t, "USA", *(s.Addresses[1].Country))
  168. assert.Equal(t, "California", *(s.Addresses[1].Province))
  169. assert.Equal(t, "EncryptedLA", **(s.Addresses[1].City))
  170. assert.Equal(t, "EncryptedNowhere", *(s.Addresses[1].Street))
  171. assert.Equal(t, "Encrypted爸", (*s.Parents)[0].Name)
  172. assert.Equal(t, "Encrypted13000000000", *((*s.Parents)[0].PhoneNumber))
  173. assert.Equal(t, "Encrypted妈", (*s.Parents)[1].Name)
  174. assert.Equal(t, (*string)(nil), (*s.Parents)[1].PhoneNumber)
  175. err = c.Decrypt(context.Background(), reflect.ValueOf(&s))
  176. require.NoError(t, err)
  177. assert.Equal(t, "小可", s.Name)
  178. assert.Equal(t, 8, s.Age)
  179. assert.Equal(t, "中国", *(s.Addresses[0].Country))
  180. assert.Equal(t, "四川", *(s.Addresses[0].Province))
  181. assert.Equal(t, "成都", **(s.Addresses[0].City))
  182. assert.Equal(t, "春熙路", *(s.Addresses[0].Street))
  183. assert.Equal(t, "USA", *(s.Addresses[1].Country))
  184. assert.Equal(t, "California", *(s.Addresses[1].Province))
  185. assert.Equal(t, "LA", **(s.Addresses[1].City))
  186. assert.Equal(t, "Nowhere", *(s.Addresses[1].Street))
  187. assert.Equal(t, "爸", (*s.Parents)[0].Name)
  188. assert.Equal(t, "13000000000", *((*s.Parents)[0].PhoneNumber))
  189. assert.Equal(t, "妈", (*s.Parents)[1].Name)
  190. assert.Equal(t, (*string)(nil), (*s.Parents)[1].PhoneNumber)
  191. }
  192. func TestWechatPayCipher_CipherNil(t *testing.T) {
  193. c := WechatPayCipher{
  194. encryptor: &encryptors.MockEncryptor{
  195. Serial: "Mock Serial",
  196. },
  197. decryptor: &decryptors.MockDecryptor{},
  198. }
  199. var s *Student
  200. _, err := c.Encrypt(context.Background(), s)
  201. require.NoError(t, err)
  202. err = c.Decrypt(context.Background(), &s)
  203. require.NoError(t, err)
  204. }
  205. func TestWechatPayCipher_CipherNonStruct(t *testing.T) {
  206. c := WechatPayCipher{
  207. encryptor: &encryptors.MockEncryptor{
  208. Serial: "Mock Serial",
  209. },
  210. decryptor: &decryptors.MockDecryptor{},
  211. }
  212. _, err := c.Encrypt(context.Background(), core.String("123"))
  213. require.Error(t, err)
  214. assert.Equal(t, "encrypt struct failed: only struct can be ciphered", err.Error())
  215. err = c.Decrypt(context.Background(), core.Int64(123))
  216. require.Error(t, err)
  217. assert.Equal(t, "decrypt struct failed: only struct can be ciphered", err.Error())
  218. }
  219. func TestWechatPayCipher_CipherValue(t *testing.T) {
  220. s := Student{
  221. Name: "小可",
  222. Age: 8,
  223. }
  224. c := WechatPayCipher{
  225. encryptor: &encryptors.MockEncryptor{
  226. Serial: "Mock Serial",
  227. },
  228. decryptor: &decryptors.MockDecryptor{},
  229. }
  230. _, err := c.Encrypt(context.Background(), s)
  231. require.Error(t, err)
  232. assert.Equal(t, "encrypt struct failed: in-place cipher requires settable input, ptr for example", err.Error())
  233. err = c.Decrypt(context.Background(), s)
  234. require.Error(t, err)
  235. assert.Equal(t, "decrypt struct failed: in-place cipher requires settable input, ptr for example", err.Error())
  236. }
  237. func TestWechatPayCipher_EncryptWithoutCertificate(t *testing.T) {
  238. s := Student{Name: "小可"}
  239. // 这是一个 SelectCertificate 会失败的 Encryptor
  240. invalidEncryptor := encryptors.NewWechatPayEncryptor(core.NewCertificateMap(nil))
  241. c := WechatPayCipher{
  242. encryptor: invalidEncryptor,
  243. decryptor: &decryptors.MockDecryptor{},
  244. }
  245. _, err := c.Encrypt(context.Background(), s)
  246. assert.Error(t, err)
  247. }
  248. func TestWechatPayCipher_EncryptWithoutSerial(t *testing.T) {
  249. patch := gomonkey.ApplyFunc(getEncryptSerial, func(ctx context.Context) (string, bool) {
  250. return "", false
  251. })
  252. defer patch.Reset()
  253. s := Student{
  254. Name: "小可",
  255. Age: 8,
  256. }
  257. c := WechatPayCipher{
  258. encryptor: &encryptors.MockEncryptor{
  259. Serial: "Mock Serial",
  260. },
  261. decryptor: &decryptors.MockDecryptor{},
  262. }
  263. _, err := c.Encrypt(context.Background(), &s)
  264. assert.Error(t, err)
  265. }
  266. func TestWechatPayCipher_DecryptWrongData(t *testing.T) {
  267. s := Student{
  268. Name: "NotEncrypted小可",
  269. Age: 8,
  270. }
  271. c := WechatPayCipher{
  272. encryptor: &encryptors.MockEncryptor{
  273. Serial: "Mock Serial",
  274. },
  275. decryptor: &decryptors.MockDecryptor{},
  276. }
  277. err := c.Decrypt(context.Background(), &s)
  278. assert.Error(t, err)
  279. s = Student{
  280. Name: "Encrypted小可",
  281. Addresses: []Address{
  282. {
  283. Country: core.String("中国"),
  284. Province: core.String("四川"),
  285. Street: core.String("UnEncrypted春熙路"),
  286. },
  287. {
  288. Country: core.String("USA"),
  289. Province: core.String("California"),
  290. Street: core.String("EncryptedNowhere"),
  291. },
  292. },
  293. }
  294. err = c.Decrypt(context.Background(), &s)
  295. assert.Error(t, err)
  296. }
  297. func TestWechatPayCipher_cipherWithWrongType(t *testing.T) {
  298. s := Student{
  299. Name: "Encrypted小可",
  300. Age: 8,
  301. }
  302. c := WechatPayCipher{
  303. encryptor: &encryptors.MockEncryptor{
  304. Serial: "Mock Serial",
  305. },
  306. decryptor: &decryptors.MockDecryptor{},
  307. }
  308. err := c.cipher(context.Background(), cipherType("invalid"), reflect.ValueOf(&s))
  309. assert.Error(t, err)
  310. }