summary refs log tree commit diff stats
path: root/lib/std/sha1.nim
diff options
context:
space:
mode:
Diffstat (limited to 'lib/std/sha1.nim')
-rw-r--r--lib/std/sha1.nim130
1 files changed, 75 insertions, 55 deletions
diff --git a/lib/std/sha1.nim b/lib/std/sha1.nim
index 8f35a44ff..213af4229 100644
--- a/lib/std/sha1.nim
+++ b/lib/std/sha1.nim
@@ -1,46 +1,44 @@
 #
 #
-#           The Nim Compiler
+#              Nim's Runtime Library
 #        (c) Copyright 2015 Nim Contributors
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
 #
-
-## **Note:** Import ``std/sha1`` to use this module
-##
-## SHA-1 (Secure Hash Algorithm 1) is a cryptographic hash function which
-## takes an input and produces a 160-bit (20-byte) hash value known as a
-## message digest.
-##
-## .. code-block::
-##    import std/sha1
-##
-##    let accessName = secureHash("John Doe")
-##    assert $accessName == "AE6E4D1209F17B460503904FAD297B31E9CF6362"
-##
-## .. code-block::
-##    import std/sha1
-##
-##    let
-##      a = secureHashFile("myFile.nim")
-##      b = parseSecureHash("10DFAEBF6BFDBC7939957068E2EFACEC4972933C")
-##
-##    if a == b:
-##      echo "Files match"
+## [SHA-1 (Secure Hash Algorithm 1)](https://en.wikipedia.org/wiki/SHA-1)
+## is a cryptographic hash function which takes an input and produces
+## a 160-bit (20-byte) hash value known as a message digest.
 ##
-## **See also:**
-## * `base64 module<base64.html>`_ implements a base64 encoder and decoder
+## See also
+## ========
+## * `base64 module<base64.html>`_ for a Base64 encoder and decoder
 ## * `hashes module<hashes.html>`_ for efficient computations of hash values for diverse Nim types
-## * `md5 module<md5.html>`_ implements the MD5 checksum algorithm
+## * `md5 module<md5.html>`_ for the MD5 checksum algorithm
 
-import strutils
-from endians import bigEndian32, bigEndian64
+runnableExamples:
+  let accessName = secureHash("John Doe")
+  assert $accessName == "AE6E4D1209F17B460503904FAD297B31E9CF6362"
+
+runnableExamples("-r:off"):
+  let
+    a = secureHashFile("myFile.nim")
+    b = parseSecureHash("10DFAEBF6BFDBC7939957068E2EFACEC4972933C")
+  assert a == b, "files don't match"
+
+
+{.deprecated: "use command `nimble install checksums` and import `checksums/sha1` instead".}
+
+import std/strutils
+from std/endians import bigEndian32, bigEndian64
+
+when defined(nimPreviewSlimSystem):
+  import std/syncio
 
 const Sha1DigestSize = 20
 
 type
-  Sha1Digest* = array[0 .. Sha1DigestSize-1, uint8]
+  Sha1Digest* = array[0 .. Sha1DigestSize - 1, uint8]
   SecureHash* = distinct Sha1Digest
 
 type
@@ -49,10 +47,14 @@ type
     state: array[5, uint32]
     buf:   array[64, byte]
 
-# This implementation of the SHA1 algorithm was ported from the Chromium OS one
+# This implementation of the SHA-1 algorithm was ported from the Chromium OS one
 # with minor modifications that should not affect its functionality.
 
 proc newSha1State*(): Sha1State =
+  ## Creates a `Sha1State`.
+  ##
+  ## If you use the `secureHash proc <#secureHash,openArray[char]>`_,
+  ## there's no need to call this function explicitly.
   result.count = 0
   result.state[0] = 0x67452301'u32
   result.state[1] = 0xEFCDAB89'u32
@@ -146,6 +148,10 @@ proc transform(ctx: var Sha1State) =
   ctx.state[4] += e
 
 proc update*(ctx: var Sha1State, data: openArray[char]) =
+  ## Updates the `Sha1State` with `data`.
+  ##
+  ## If you use the `secureHash proc <#secureHash,openArray[char]>`_,
+  ## there's no need to call this function explicitly.
   var i = ctx.count mod 64
   var j = 0
   var len = data.len
@@ -177,6 +183,10 @@ proc update*(ctx: var Sha1State, data: openArray[char]) =
   ctx.count += data.len
 
 proc finalize*(ctx: var Sha1State): Sha1Digest =
+  ## Finalizes the `Sha1State` and returns a `Sha1Digest`.
+  ##
+  ## If you use the `secureHash proc <#secureHash,openArray[char]>`_,
+  ## there's no need to call this function explicitly.
   var cnt = uint64(ctx.count * 8)
   # a 1 bit
   update(ctx, "\x80")
@@ -195,54 +205,72 @@ proc finalize*(ctx: var Sha1State): Sha1Digest =
 # Public API
 
 proc secureHash*(str: openArray[char]): SecureHash =
-  ## Generates a ``SecureHash`` from a ``str``.
+  ## Generates a `SecureHash` from `str`.
   ##
   ## **See also:**
-  ## * `secureHashFile proc <#secureHashFile,string>`_ for generating a ``SecureHash`` from a file
-  ## * `parseSecureHash proc <#parseSecureHash,string>`_ for converting a string ``hash`` to ``SecureHash``
+  ## * `secureHashFile proc <#secureHashFile,string>`_ for generating a `SecureHash` from a file
+  ## * `parseSecureHash proc <#parseSecureHash,string>`_ for converting a string `hash` to `SecureHash`
   runnableExamples:
     let hash = secureHash("Hello World")
     assert hash == parseSecureHash("0A4D55A8D778E5022FAB701977C5D840BBC486D0")
+
   var state = newSha1State()
   state.update(str)
   SecureHash(state.finalize())
 
 proc secureHashFile*(filename: string): SecureHash =
-  ## Generates a ``SecureHash`` from a file.
+  ## Generates a `SecureHash` from a file.
   ##
   ## **See also:**
-  ## * `secureHash proc <#secureHash,openArray[char]>`_ for generating a ``SecureHash`` from a string
-  ## * `parseSecureHash proc <#parseSecureHash,string>`_ for converting a string ``hash`` to ``SecureHash``
-  secureHash(readFile(filename))
+  ## * `secureHash proc <#secureHash,openArray[char]>`_ for generating a `SecureHash` from a string
+  ## * `parseSecureHash proc <#parseSecureHash,string>`_ for converting a string `hash` to `SecureHash`
+  const BufferLength = 8192
+
+  let f = open(filename)
+  var state = newSha1State()
+  var buffer = newString(BufferLength)
+  while true:
+    let length = readChars(f, buffer)
+    if length == 0:
+      break
+    buffer.setLen(length)
+    state.update(buffer)
+    if length != BufferLength:
+      break
+  close(f)
+
+  SecureHash(state.finalize())
 
 proc `$`*(self: SecureHash): string =
-  ## Returns the string representation of a ``SecureHash``.
+  ## Returns the string representation of a `SecureHash`.
   ##
   ## **See also:**
-  ## * `secureHash proc <#secureHash,openArray[char]>`_ for generating a ``SecureHash`` from a string
+  ## * `secureHash proc <#secureHash,openArray[char]>`_ for generating a `SecureHash` from a string
   runnableExamples:
     let hash = secureHash("Hello World")
     assert $hash == "0A4D55A8D778E5022FAB701977C5D840BBC486D0"
+
   result = ""
   for v in Sha1Digest(self):
     result.add(toHex(int(v), 2))
 
 proc parseSecureHash*(hash: string): SecureHash =
-  ## Converts a string ``hash`` to ``SecureHash``.
+  ## Converts a string `hash` to a `SecureHash`.
   ##
   ## **See also:**
-  ## * `secureHash proc <#secureHash,openArray[char]>`_ for generating a ``SecureHash`` from a string
-  ## * `secureHashFile proc <#secureHashFile,string>`_ for generating a ``SecureHash`` from a file
+  ## * `secureHash proc <#secureHash,openArray[char]>`_ for generating a `SecureHash` from a string
+  ## * `secureHashFile proc <#secureHashFile,string>`_ for generating a `SecureHash` from a file
   runnableExamples:
     let
       hashStr = "0A4D55A8D778E5022FAB701977C5D840BBC486D0"
       secureHash = secureHash("Hello World")
     assert secureHash == parseSecureHash(hashStr)
+
   for i in 0 ..< Sha1DigestSize:
     Sha1Digest(result)[i] = uint8(parseHexInt(hash[i*2] & hash[i*2 + 1]))
 
 proc `==`*(a, b: SecureHash): bool =
-  ## Checks if two ``SecureHash`` values are identical.
+  ## Checks if two `SecureHash` values are identical.
   runnableExamples:
     let
       a = secureHash("Hello World")
@@ -250,18 +278,10 @@ proc `==`*(a, b: SecureHash): bool =
       c = parseSecureHash("0A4D55A8D778E5022FAB701977C5D840BBC486D0")
     assert a != b
     assert a == c
+
   # Not a constant-time comparison, but that's acceptable in this context
   Sha1Digest(a) == Sha1Digest(b)
 
-when isMainModule:
-  let hash1 = secureHash("a93tgj0p34jagp9[agjp98ajrhp9aej]")
-  doAssert hash1 == hash1
-  doAssert parseSecureHash($hash1) == hash1
-
-  template checkVector(s, exp: string) =
-    doAssert secureHash(s) == parseSecureHash(exp)
-
-  checkVector("", "da39a3ee5e6b4b0d3255bfef95601890afd80709")
-  checkVector("abc", "a9993e364706816aba3e25717850c26c9cd0d89d")
-  checkVector("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
-              "84983e441c3bd26ebaae4aa1f95129e5e54670f1")
+proc isValidSha1Hash*(s: string): bool =
+  ## Checks if a string is a valid sha1 hash sum.
+  s.len == 40 and allCharsInSet(s, HexDigits)
\ No newline at end of file