digest.bmx 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. '
  2. ' Copyright (C) 2019-2020 Bruce A Henderson
  3. '
  4. ' This software is provided 'as-is', without any express or implied
  5. ' warranty. In no event will the authors be held liable for any damages
  6. ' arising from the use of this software.
  7. '
  8. ' Permission is granted to anyone to use this software for any purpose,
  9. ' including commercial applications, and to alter it and redistribute it
  10. ' freely, subject to the following restrictions:
  11. '
  12. ' 1. The origin of this software must not be misrepresented; you must not
  13. ' claim that you wrote the original software. If you use this software
  14. ' in a product, an acknowledgment in the product documentation would be
  15. ' appreciated but is not required.
  16. ' 2. Altered source versions must be plainly marked as such, and must not be
  17. ' misrepresented as being the original software.
  18. ' 3. This notice may not be removed or altered from any source distribution.
  19. '
  20. SuperStrict
  21. Rem
  22. bbdoc: Message Digests and hashes.
  23. End Rem
  24. Module Crypto.Digest
  25. Import "common.bmx"
  26. Rem
  27. bbdoc: Gets a digest of the specified @name.
  28. about: A #TNoSuchAlgorithmException is thrown if the requested digest is not available.
  29. End Rem
  30. Function GetMessageDigest:TMessageDigest(name:String)
  31. Local d:TMessageDigest
  32. Local register:TDigestRegister=digest_registry
  33. While register
  34. d=register.GetDigest(name)
  35. If d Exit
  36. register = register._succ
  37. Wend
  38. If Not d Then
  39. Throw New TNoSuchAlgorithmException("Digest not available : " + name)
  40. End If
  41. Return d
  42. End Function
  43. Rem
  44. bbdoc: Returns a list of all currently registered digests.
  45. about: The returned digest names can be used with #GetMessageDigest to get a #TMessageDigest instance.
  46. End Rem
  47. Function ListDigests:TArrayList<String>()
  48. Local list:TArrayLIst<String> = New TArrayList<String>()
  49. Local register:TDigestRegister=digest_registry
  50. While register
  51. list.Add(register.ToString())
  52. register = register._succ
  53. Wend
  54. list.Sort()
  55. Return list
  56. End Function
  57. Rem
  58. bbdoc: This exception is thrown when a particular cryptographic algorithm is requested but is not available in the environment.
  59. End Rem
  60. Type TNoSuchAlgorithmException Extends TBlitzException
  61. Field message:String
  62. Method New(message:String)
  63. Self.message = message
  64. End Method
  65. Method ToString:String() Override
  66. Return message
  67. End Method
  68. End Type
  69. Rem
  70. bbdoc: An abstract base type for message digest implementations.
  71. End Rem
  72. Type TMessageDigest
  73. Field digestPtr:Byte Ptr
  74. Method Update:Int(data:Byte Ptr, dataLen:Int) Abstract
  75. Method Finish:Int(digest:Byte[]) Abstract
  76. Method OutBytes:Int() Abstract
  77. Rem
  78. bbdoc: Calculates a digest for the given #String input @data.
  79. returns: A #String representation of the digest.
  80. End Rem
  81. Method Digest:String(data:String)
  82. Return BytesToHex(DigestBytes(data))
  83. End Method
  84. Rem
  85. bbdoc: Calculates a digest for the given #TStream input @stream.
  86. returns: A #String representation of the digest.
  87. End Rem
  88. Method Digest:String(stream:TStream)
  89. Return BytesToHex(DigestBytes(stream))
  90. End Method
  91. Rem
  92. bbdoc: Calculates a digest for the given #String input @data.
  93. returns: A byte array representation of the digest.
  94. End Rem
  95. Method DigestBytes:Byte[](data:String)
  96. Local buf:Byte Ptr = data.ToUTF8String()
  97. Update(buf, Int(strlen_(buf)))
  98. Local res:Byte[OutBytes()]
  99. Finish(res)
  100. MemFree(buf)
  101. Return res
  102. End Method
  103. Rem
  104. bbdoc: Calculates a digest for the given #TStream input @stream.
  105. returns: A bytes array representation of the digest.
  106. End Rem
  107. Method DigestBytes:Byte[](stream:TStream)
  108. Local buf:Byte[8192]
  109. Local bytesRead:Long
  110. Repeat
  111. bytesRead = stream.Read(buf, buf.length)
  112. If bytesRead Then
  113. Update(buf, Int(bytesRead))
  114. End If
  115. Until bytesRead <= 0
  116. If Not bytesRead Then
  117. Local res:Byte[OutBytes()]
  118. Finish(res)
  119. Return res
  120. End If
  121. Return Null
  122. End Method
  123. Method Delete()
  124. If digestPtr Then
  125. bmx_digest_free(digestPtr)
  126. digestPtr = Null
  127. End If
  128. End Method
  129. End Type
  130. Rem
  131. bbdoc: Returns a hex representation of #Byte array @bytes.
  132. End Rem
  133. Function BytesToHex:String(bytes:Byte[], uppercase:Int = False)
  134. Return bmx_digest_bytes_to_hex(bytes, bytes.length, uppercase)
  135. End Function
  136. Rem
  137. bbdoc: Returns a hex representation of @size @bytes.
  138. End Rem
  139. Function BytesToHex:String(bytes:Byte Ptr, size:Int, uppercase:Int = False)
  140. Return bmx_digest_bytes_to_hex(bytes, size, uppercase)
  141. End Function
  142. Private
  143. Global digest_registry:TDigestRegister
  144. Public
  145. Rem
  146. bbdoc: A register of available message digests and cryptographic functions.
  147. about: This can be extended to add new digests to the register.
  148. End Rem
  149. Type TDigestRegister
  150. Field _succ:TDigestRegister
  151. Method New()
  152. _succ=digest_registry
  153. digest_registry=Self
  154. End Method
  155. Rem
  156. bbdoc: Gets an instance of a messages digest.
  157. returns: The message digest or #Null if one of the given name does not exist.
  158. about: This method must be implemented by extending types.
  159. End Rem
  160. Method GeTDigest:TMessageDigest( name:String ) Abstract
  161. End Type