encrypted-attr.spec.js 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. 'use strict'
  2. const EncryptedAttributes = require('..')
  3. const expect = require('unexpected')
  4. describe('encrypted attributes', function () {
  5. beforeEach(function () {
  6. this.options = {
  7. keys: {
  8. k1: 'ZZIMKOjE6NPLI0JgB3QlLvhcqLr5Bq+F9a25/bZqQAw=',
  9. k2: 'scJmBOP559QM/Cj0nHL5Aj8XOgUIV7MkpsyDu5BmG0U='
  10. },
  11. keyId: 'k1',
  12. verifyId: true
  13. }
  14. })
  15. it('should encrypt value via helper method', function () {
  16. let enc = EncryptedAttributes(['secret'], this.options)
  17. let obj = {id: 1}
  18. // expect: YWVzLTI1Ni1nY20kMSRrMQ==$sK91YfUvv+O8Jx/m$OOQniq8=$WLbWYz7uCQBTNO3Fc+5UvA
  19. expect(enc.encryptAttribute(obj, 'value'), 'not to equal', 'value')
  20. .and('to begin with', 'YWVzLTI1Ni1nY20k')
  21. })
  22. it('should encrypt object attributes', function () {
  23. let enc = EncryptedAttributes(['secret'], this.options)
  24. let obj = {id: 1, secret: 'value'}
  25. // expect: YWVzLTI1Ni1nY20kMSRrMQ==$sK91YfUvv+O8Jx/m$OOQniq8=$WLbWYz7uCQBTNO3Fc+5UvA
  26. enc.encryptAll(obj)
  27. expect(obj.secret, 'not to equal', 'value').and('to begin with', 'YWVzLTI1Ni1nY20k')
  28. })
  29. it('should encrypt nested attributes', function () {
  30. let enc = EncryptedAttributes(['secret.data'], this.options)
  31. let obj = {id: 1, secret: {data: 'value', dataLength: 5}}
  32. // expect: YWVzLTI1Ni1nY20kMSRrMQ==$sK91YfUvv+O8Jx/m$OOQniq8=$WLbWYz7uCQBTNO3Fc+5UvA
  33. enc.encryptAll(obj)
  34. expect(obj.secret.data, 'not to equal', 'value').and('to begin with', 'YWVzLTI1Ni1nY20k')
  35. expect(obj.secret.dataLength, 'to equal', 5)
  36. })
  37. it('should not create missing nested attributes', function () {
  38. let enc = EncryptedAttributes(['secret.data'], this.options)
  39. let obj = {id: 1}
  40. enc.encryptAll(obj)
  41. expect(obj.secret, 'to be undefined')
  42. })
  43. it('should not encrypt null', function () {
  44. let enc = EncryptedAttributes(['secret'], this.options)
  45. let obj = {id: 1}
  46. expect(enc.encryptAttribute(obj, null), 'to be null')
  47. })
  48. it('should not encrypt undefined', function () {
  49. let enc = EncryptedAttributes(['secret'], this.options)
  50. let obj = {id: 1}
  51. expect(enc.encryptAttribute(obj, undefined), 'to be undefined')
  52. })
  53. it('should not encrypt already encrypted value', function () {
  54. let enc = EncryptedAttributes(['secret'], this.options)
  55. let obj = {id: 1}
  56. let encrypted = 'YWVzLTI1Ni1nY20kMSRrMQ==$sK91YfUvv+O8Jx/m$OOQniq8=$WLbWYz7uCQBTNO3Fc+5UvA'
  57. expect(enc.encryptAttribute(obj, encrypted), 'to equal', encrypted)
  58. })
  59. it('should throw when encrypting non-string value', function () {
  60. let enc = EncryptedAttributes(['secret'], this.options)
  61. let obj = {id: 1}
  62. expect(() => enc.encryptAttribute(obj, 42), 'to throw', /must be a string/i)
  63. })
  64. it('should throw when encrypting without id', function () {
  65. let enc = EncryptedAttributes(['secret'], this.options)
  66. let obj = {}
  67. expect(() => enc.encryptAttribute(obj, 'value'), 'to throw', /cannot encrypt without 'id'/i)
  68. })
  69. it('should encrypt without id when verify id option is false', function () {
  70. let enc = EncryptedAttributes(['secret'], Object.assign(this.options, {verifyId: false}))
  71. let obj = {}
  72. expect(() => enc.encryptAttribute(obj, 'value'), 'not to throw')
  73. })
  74. it('should decrypt value via helper method', function () {
  75. let enc = EncryptedAttributes(['secret'], this.options)
  76. let obj = {id: 1}
  77. let encrypted = 'YWVzLTI1Ni1nY20kMSRrMQ==$sK91YfUvv+O8Jx/m$OOQniq8=$WLbWYz7uCQBTNO3Fc+5UvA'
  78. expect(enc.decryptAttribute(obj, encrypted), 'to equal', 'value')
  79. })
  80. it('should decrypt object attributes', function () {
  81. let enc = EncryptedAttributes(['secret'], this.options)
  82. let obj = enc.encryptAll({id: 1, secret: 'value'})
  83. enc.decryptAll(obj)
  84. expect(obj.secret, 'to equal', 'value')
  85. })
  86. it('should decrypt nested attributes', function () {
  87. let enc = EncryptedAttributes(['secret.data'], this.options)
  88. let obj = enc.encryptAll({id: 1, secret: {data: 'value', dataLength: 5}})
  89. enc.decryptAll(obj)
  90. expect(obj.secret.data, 'to equal', 'value')
  91. expect(obj.secret.dataLength, 'to equal', 5)
  92. })
  93. it('should not create missing nested attributes', function () {
  94. let enc = EncryptedAttributes(['secret.data'], this.options)
  95. let obj = {id: 1}
  96. enc.decryptAll(obj)
  97. expect(obj.secret, 'to be undefined')
  98. })
  99. it('should not decrypt null', function () {
  100. let enc = EncryptedAttributes(['secret'], this.options)
  101. let obj = {id: 1}
  102. expect(enc.decryptAttribute(obj, null), 'to be null')
  103. })
  104. it('should not decrypt undefined', function () {
  105. let enc = EncryptedAttributes(['secret'], this.options)
  106. let obj = {id: 1}
  107. expect(enc.decryptAttribute(obj, undefined), 'to be undefined')
  108. })
  109. it('should not decrypt non-string value', function () {
  110. let enc = EncryptedAttributes(['secret'], this.options)
  111. let obj = {id: 1}
  112. expect(enc.decryptAttribute(obj, 42), 'to equal', 42)
  113. })
  114. it('should not decrypt value that is not encrypted', function () {
  115. let enc = EncryptedAttributes(['secret'], this.options)
  116. let obj = {id: 1}
  117. expect(enc.decryptAttribute(obj, 'value'), 'to equal', 'value')
  118. })
  119. it('should throw when decrypting with invalid id', function () {
  120. let enc = EncryptedAttributes(['secret'], this.options)
  121. let obj = {id: 1}
  122. // aad: aes-256-gcm$02$k1
  123. let invalidId = 'YWVzLTI1Ni1nY20kMiRrMQ==$sK91YfUvv+O8Jx/m$OOQniq8=$WLbWYz7uCQBTNO3Fc+5UvA'
  124. expect(() => enc.decryptAttribute(obj, invalidId), 'to throw', /invalid id/i)
  125. })
  126. it('should throw when decrypting with invalid key id', function () {
  127. let enc = EncryptedAttributes(['secret'], this.options)
  128. let obj = {id: 1}
  129. // aad: aes-256-gcm$01$k3
  130. let invalidKeyId = 'YWVzLTI1Ni1nY20kMSRrMw==$sK91YfUvv+O8Jx/m$OOQniq8=$WLbWYz7uCQBTNO3Fc+5UvA'
  131. expect(() => enc.decryptAttribute(obj, invalidKeyId), 'to throw', /invalid key id/i)
  132. })
  133. it('should throw when decrypting with wrong key', function () {
  134. let enc = EncryptedAttributes(['secret'], this.options)
  135. let obj = {id: 1}
  136. // aad: aes-256-gcm$01$k2
  137. let wrongKey = 'YWVzLTI1Ni1nY20kMSRrMg==$sK91YfUvv+O8Jx/m$OOQniq8=$WLbWYz7uCQBTNO3Fc+5UvA'
  138. expect(() => enc.decryptAttribute(obj, wrongKey), 'to throw', /unable to auth/i)
  139. })
  140. it('should throw when decrypting with wrong auth tag', function () {
  141. let enc = EncryptedAttributes(['secret'], this.options)
  142. let obj = {id: 1}
  143. // aad: aes-256-gcm$01$k1
  144. let wrongAuthTag = 'YWVzLTI1Ni1nY20kMSRrMQ==$sK91YfUvv+O8Jx/m$OOQniq8=$VLbWYz7uCQBTNO3Fc+5UvA'
  145. expect(() => enc.decryptAttribute(obj, wrongAuthTag), 'to throw', /unable to auth/i)
  146. })
  147. it('should throw when decrypting without id', function () {
  148. let enc = EncryptedAttributes(['secret'], this.options)
  149. let obj = {}
  150. let encrypted = 'YWVzLTI1Ni1nY20kMSRrMQ==$sK91YfUvv+O8Jx/m$OOQniq8=$WLbWYz7uCQBTNO3Fc+5UvA'
  151. expect(() => enc.decryptAttribute(obj, encrypted), 'to throw', /cannot decrypt without 'id'/i)
  152. })
  153. it('should decrypt without id when verify id option is false', function () {
  154. let enc = EncryptedAttributes(['secret'], Object.assign(this.options, {verifyId: false}))
  155. let obj = {}
  156. let encrypted = 'YWVzLTI1Ni1nY20kMSRrMQ==$sK91YfUvv+O8Jx/m$OOQniq8=$WLbWYz7uCQBTNO3Fc+5UvA'
  157. expect(() => enc.decryptAttribute(obj, encrypted), 'not to throw')
  158. })
  159. })