summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/hash.ur2
-rw-r--r--src/hash.urs2
-rw-r--r--src/hashFFI.cc27
-rw-r--r--src/hashFFI.h1
-rw-r--r--src/hashFFI.urs2
5 files changed, 34 insertions, 0 deletions
diff --git a/src/hash.ur b/src/hash.ur
index 7492dd0..cca79d7 100644
--- a/src/hash.ur
+++ b/src/hash.ur
@@ -14,3 +14,5 @@ specific language governing permissions and limitations under the License. *)
type digest = string
val md5 = HashFFI.md5
+
+val sha1 = HashFFI.sha1
diff --git a/src/hash.urs b/src/hash.urs
index bc4a543..b0bfb69 100644
--- a/src/hash.urs
+++ b/src/hash.urs
@@ -19,3 +19,5 @@ val sql_digest : sql_injectable digest
val sql_maxable_digest : sql_maxable digest
val md5 : blob -> digest
+
+val sha1 : blob -> digest
diff --git a/src/hashFFI.cc b/src/hashFFI.cc
index ab20030..f349ba4 100644
--- a/src/hashFFI.cc
+++ b/src/hashFFI.cc
@@ -18,6 +18,7 @@
#include <cstdio>
#include <openssl/md5.h>
+#include <openssl/sha.h>
extern "C" {
#include <urweb/urweb_cpp.h>
}
@@ -70,3 +71,29 @@ uw_Basis_string uw_HashFFI_md5(uw_context* const context,
"failed to properly terminate digest");
return result;
}
+
+uw_Basis_string uw_HashFFI_sha1(uw_context* const context,
+ const uw_Basis_blob input) {
+ using Digest = std::array<unsigned char, SHA_DIGEST_LENGTH>;
+ // Perform the SHA-1 operation.
+ Digest raw_result;
+ SHA1(reinterpret_cast<unsigned char*>(input.data), input.size,
+ raw_result.data());
+ // Convert it to a hex string. This will be twice as large (two hex digits
+ // per byte), plus an additional byte for the null terminator.
+ const auto result_length = 2 * raw_result.size() + 1;
+ uw_Basis_string result =
+ reinterpret_cast<uw_Basis_string>(uw_malloc(context, result_length));
+ Assert(context, result, BOUNDED_RETRY,
+ "unable to allocate memory for digest");
+ for (Digest::size_type i = 0; i < raw_result.size(); i++) {
+ sprintf(result + 2 * i, "%02x", raw_result[i]);
+ }
+ // Make sure the string is properly terminated.
+ for (std::size_t i = 0; i < result_length - 2; i++) {
+ Assert(context, result[i] != '\0', "null byte in digest");
+ }
+ Assert(context, result[result_length - 1] == '\0',
+ "failed to properly terminate digest");
+ return result;
+}
diff --git a/src/hashFFI.h b/src/hashFFI.h
index 5ff8ea3..a454b99 100644
--- a/src/hashFFI.h
+++ b/src/hashFFI.h
@@ -22,6 +22,7 @@ extern "C" {
#include <urweb/urweb_cpp.h>
uw_Basis_string uw_HashFFI_md5(struct uw_context*, const uw_Basis_blob);
+uw_Basis_string uw_HashFFI_sha1(struct uw_context*, const uw_Basis_blob);
#ifdef __cplusplus
}
diff --git a/src/hashFFI.urs b/src/hashFFI.urs
index 55acadd..f9c6ba5 100644
--- a/src/hashFFI.urs
+++ b/src/hashFFI.urs
@@ -12,3 +12,5 @@ CONDITIONS OF ANY KIND, either express or implied. See the License for the
specific language governing permissions and limitations under the License. *)
val md5 : blob -> string
+
+val sha1 : blob -> string