-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
12 changed files
with
346 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
.vessel/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,19 @@ | ||
# Crypto Package for Motoko | ||
|
||
## Packages | ||
|
||
| Package Name | Description | Path | | ||
|--------------|-------------|------| | ||
| SHA | SHA224 and SHA256 hash algorithms as defined in FIPS 180-4 | crypto/SHA | | ||
|
||
## Usage | ||
|
||
```motoko | ||
SHA256.sum(Blob.toArray(Text.encodeUtf8("hello world\n")) | ||
// "A948904F2F0F479B8F8197694B30184B0D2ED1C1CD2A1EC0FB85D299A192A447" | ||
let h = SHA256.New(); | ||
h.write(Blob.toArray(Text.encodeUtf8("hello world\n"))); | ||
h.sum([]); | ||
// "A948904F2F0F479B8F8197694B30184B0D2ED1C1CD2A1EC0FB85D299A192A447" | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
let upstream = https://github.com/aviate-labs/package-set/releases/download/v0.1.3/package-set.dhall sha256:ca68dad1e4a68319d44c587f505176963615d533b8ac98bdb534f37d1d6a5b47 | ||
in upstream |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
module Hash { | ||
public type Hash = { | ||
// Returns the block size of the hash. | ||
blockSize() : Nat; | ||
// Returns the checksum data. | ||
checkSum() : [Nat8]; | ||
// Resets the hash to its initial state. | ||
reset() : (); | ||
// Returns the number of bytes that sum will return. | ||
size() : Nat; | ||
// Adds the current hash to the resulting slice. | ||
// The underlying hash is not modified. | ||
sum(bs : [Nat8]) : [Nat8]; | ||
// Adds data to the running hash. | ||
write(bs : [Nat8]) : (); | ||
}; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,138 @@ | ||
import Array "mo:base/Array"; | ||
import Binary "mo:encoding/Binary"; | ||
import Iter "mo:base/Iter"; | ||
import Nat32 "mo:base/Nat32"; | ||
import Nat64 "mo:base/Nat64"; | ||
|
||
import Hash "../Hash"; | ||
import Util "../Utilities"; | ||
|
||
/// For internal use only. | ||
module { | ||
// First thirty-two bits of the fractional parts of the cube roots of the | ||
// first sixty-four prime numbers. | ||
private let K : [Nat32] = [ | ||
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, | ||
0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, | ||
0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786, | ||
0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, | ||
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, | ||
0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, | ||
0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b, | ||
0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, | ||
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, | ||
0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, | ||
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2, | ||
]; | ||
|
||
// Initial hash value, H(0). | ||
private let H256 : [Nat32] = [ | ||
0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, | ||
0x1f83d9ab, 0x5be0cd19, | ||
]; | ||
|
||
public class SHA2( | ||
initialState : [Nat32], | ||
hashSize : Nat, | ||
) : Hash.Hash = { | ||
private var h : [var Nat32] = Array.thaw<Nat32>(initialState); | ||
private var x : [var Nat8] = Array.init<Nat8>(64, 0); | ||
private var nx : Nat = 0; | ||
private var len : Nat64 = 0; | ||
|
||
public func blockSize() : Nat { 64; }; | ||
|
||
public func reset() : () { | ||
h := Array.thaw<Nat32>(initialState); | ||
x := Array.init<Nat8>(64, 0); | ||
nx := 0; | ||
len := 0; | ||
}; | ||
|
||
public func size() : Nat { hashSize; }; | ||
|
||
public func sum(bs : [Nat8]) : [Nat8] { | ||
Array.append(bs, checkSum()); | ||
}; | ||
|
||
public func checkSum() : [Nat8] { | ||
let n = len; | ||
var tmp = Array.init<Nat8>(64, 0); | ||
tmp[0] := 0x80; | ||
if (Nat64.toNat(len) % 64 < 56) { | ||
write(Util.takeN<Nat8>( | ||
56 - Nat64.toNat(len) % 64, | ||
Array.freeze(tmp), | ||
)); | ||
} else { | ||
write(Util.takeN<Nat8>( | ||
64 + 56 - Nat64.toNat(len) % 64, | ||
Array.freeze(tmp), | ||
)); | ||
}; | ||
write(Binary.BigEndian.fromNat64(n << 3)); | ||
var digest : [Nat8] = []; | ||
label l for (i in h.keys()) { | ||
if (i == 7 and hashSize == 28) { break l; }; | ||
digest := Array.append(digest, Binary.BigEndian.fromNat32(h[i])); | ||
}; | ||
digest; | ||
}; | ||
|
||
public func write(bs : [Nat8]) : () { | ||
var p = bs; | ||
len +%= Nat64.fromNat(bs.size()); | ||
if (0 < nx) { | ||
let n = Util.copy<Nat8>(nx, x, p); | ||
nx += n; | ||
if (nx == 64) { | ||
block(Array.freeze(x)); | ||
nx := 0; | ||
}; | ||
p := Util.removeN(n, p); | ||
}; | ||
if (64 <= p.size()) { | ||
let n = Nat64.toNat(Nat64.fromNat(p.size()) & (^63)); | ||
block(Util.takeN(n, p)); | ||
p := Util.removeN(n, p); | ||
}; | ||
if (0 < p.size()) { | ||
nx := Util.copy<Nat8>(0, x, p); | ||
}; | ||
}; | ||
|
||
private func block(bs : [Nat8]) { | ||
var p = bs; | ||
var w : [var Nat32] = Array.init<Nat32>(64, 0); | ||
var h0 = h[0]; var h1 = h[1]; var h2 = h[2]; var h3 = h[3]; | ||
var h4 = h[4]; var h5 = h[5]; var h6 = h[6]; var h7 = h[7]; | ||
while (64 <= p.size()) { | ||
for (i in Iter.range(0, 15)) { | ||
let j = i * 4; | ||
w[i] := Util.nat8to32(p[j]) << 24 | Util.nat8to32(p[j+1]) << 16 | ||
| Util.nat8to32(p[j+2]) << 8 | Util.nat8to32(p[j+3]); | ||
}; | ||
for (i in Iter.range(16, 63)) { | ||
let v1 = w[i-2]; | ||
let t1 = (Nat32.bitrotRight(v1, 17) ^ Nat32.bitrotRight(v1, 19)) ^ (v1 >> 10); | ||
let v2 = w[i-15]; | ||
let t2 = (Nat32.bitrotRight(v2, 7) ^ Nat32.bitrotRight(v2, 18)) ^ (v2 >> 3); | ||
w[i] := t1 +% w[i-7] +% t2 +% w[i - 16]; | ||
}; | ||
var a = h0; var b = h1; var c = h2; var d = h3; | ||
var e = h4; var f = h5; var g = h6; var h = h7; | ||
for (i in Iter.range(0, 63)) { | ||
let t1 = h +% (Nat32.bitrotRight(e, 6) ^ Nat32.bitrotRight(e, 11) ^ Nat32.bitrotRight(e, 25)) +% ((e & f) ^ (^e & g)) +% K[i] +% w[i]; | ||
let t2 = (Nat32.bitrotRight(a, 2) ^ Nat32.bitrotRight(a, 13) ^ Nat32.bitrotRight(a, 22)) +% ((a & b) ^ (a & c) ^ (b & c)); | ||
h := g; g := f; f := e; e := d +% t1; | ||
d := c; c := b; b := a; a := t1 +% t2; | ||
}; | ||
h0 +%= a; h1 +%= b; h2 +%= c; h3 +%= d; | ||
h4 +%= e; h5 +%= f; h6 +%= g; h7 +%= h; | ||
p := Util.removeN(64, p); | ||
}; | ||
h[0] := h0; h[1] := h1; h[2] := h2; h[3] := h3; | ||
h[4] := h4; h[5] := h5; h[6] := h6; h[7] := h7; | ||
}; | ||
}; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import SHA2 "SHA2"; | ||
|
||
import Hash "../Hash"; | ||
|
||
module SHA224 { | ||
// Initial hash value, H(0). | ||
private let H224 : [Nat32] = [ | ||
0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939, 0xffc00b31, 0x68581511, | ||
0x64f98fa7, 0xbefa4fa4, | ||
]; | ||
|
||
/// Returns the SHA224 checkum of the data. | ||
public func sum(bs : [Nat8]) : [Nat8] { | ||
let h = New(); | ||
h.write(bs); | ||
h.checkSum() | ||
}; | ||
|
||
public func New() : Hash.Hash { SHA2.SHA2(H224, 28); }; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import SHA2 "SHA2"; | ||
|
||
import Hash "../Hash"; | ||
|
||
module SHA224 { | ||
// Initial hash value, H(0). | ||
private let H256 : [Nat32] = [ | ||
0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, | ||
0x1f83d9ab, 0x5be0cd19, | ||
]; | ||
|
||
/// Returns the SHA256 checksum of the data. | ||
public func sum(bs : [Nat8]) : [Nat8] { | ||
let h = New(); | ||
h.write(bs); | ||
h.checkSum(); | ||
}; | ||
|
||
public func New() : Hash.Hash { SHA2.SHA2(H256, 32); }; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
import Array "mo:base/Array"; | ||
import Nat8 "mo:base/Nat8"; | ||
import Nat32 "mo:base/Nat32"; | ||
|
||
module Utilities { | ||
public func copy<T>( | ||
n : Nat, // Position to start writing. | ||
dst : [var T], | ||
src : [T], | ||
) : Nat { | ||
let l = dst.size(); | ||
for (i in src.keys()) { | ||
if (l <= i) return l; | ||
dst[n + i] := src[i]; | ||
}; | ||
src.size(); | ||
}; | ||
|
||
public func removeN<T>( | ||
n : Nat, // Number to remove. | ||
xs : [T], | ||
) : [T] { | ||
Array.tabulate<T>( | ||
xs.size() - n, | ||
func (i : Nat) : T { | ||
xs[i + n]; | ||
}, | ||
); | ||
}; | ||
|
||
public func takeN<T>( | ||
n : Nat, // Number to take. | ||
xs : [T], | ||
) : [T] { | ||
Array.tabulate<T>( | ||
n, | ||
func (i : Nat) : T { | ||
xs[i]; | ||
}, | ||
); | ||
}; | ||
|
||
public func nat8to32(n : Nat8) : Nat32 { | ||
Nat32.fromNat(Nat8.toNat(n)); | ||
}; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import Blob "mo:base/Blob"; | ||
import Hex "mo:encoding/Hex"; | ||
import Text "mo:base/Text"; | ||
|
||
import SHA224 "../src/SHA/SHA224"; | ||
|
||
let sum224 = SHA224.sum(Blob.toArray(Text.encodeUtf8("hello world\n"))); | ||
assert(Hex.encode(sum224) == "95041DD60AB08C0BF5636D50BE85FE9790300F39EB84602858A9B430"); | ||
|
||
for (v in [ | ||
("", "D14A028C2A3A2BC9476102BB288234C415A2B01F828EA62AC5B3E42F"), | ||
("a", "ABD37534C7D9A2EFB9465DE931CD7055FFDB8879563AE98078D6D6D5"), | ||
("ab", "DB3CDA86D4429A1D39C148989566B38F7BDA0156296BD364BA2F878B"), | ||
("abc", "23097D223405D8228642A477BDA255B32AADBCE4BDA0B3F7E36C9DA7"), | ||
("abcd", "A76654D8E3550E9A2D67A0EEB6C67B220E5885EDDD3FDE135806E601"), | ||
("abcde", "BDD03D560993E675516BA5A50638B6531AC2AC3D5847C61916CFCED6"), | ||
("abcdef", "7043631CB415556A275A4EBECB802C74EE9F6153908E1792A90B6A98"), | ||
("abcdefg", "D1884E711701AD81ABE0C77A3B0EA12E19BA9AF64077286C72FC602D"), | ||
("abcdefgh", "17EB7D40F0356F8598E89EAFAD5F6C759B1F822975D9C9B737C8A517"), | ||
("abcdefghi", "AEB35915346C584DB820D2DE7AF3929FFAFEF9222A9BCB26516C7334"), | ||
("abcdefghij", "D35E1E5AF29DDB0D7E154357DF4AD9842AFEE527C689EE547F753188"), | ||
].vals()) { | ||
assert(Hex.encode(SHA224.sum(Blob.toArray(Text.encodeUtf8(v.0)))) == v.1); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
import Blob "mo:base/Blob"; | ||
import Hex "mo:encoding/Hex"; | ||
import Text "mo:base/Text"; | ||
|
||
import Debug "mo:base/Debug"; | ||
|
||
import SHA256 "../src/SHA/SHA256"; | ||
|
||
let sum256 = SHA256.sum(Blob.toArray(Text.encodeUtf8("hello world\n"))); | ||
assert(Hex.encode(sum256) == "A948904F2F0F479B8F8197694B30184B0D2ED1C1CD2A1EC0FB85D299A192A447"); | ||
|
||
let h = SHA256.New(); | ||
h.write(Blob.toArray(Text.encodeUtf8("hello world\n"))); | ||
assert(Hex.encode(sum256) == Hex.encode(h.sum([]))); | ||
|
||
for (v in [ | ||
("", "E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855"), | ||
("a", "CA978112CA1BBDCAFAC231B39A23DC4DA786EFF8147C4E72B9807785AFEE48BB"), | ||
("ab", "FB8E20FC2E4C3F248C60C39BD652F3C1347298BB977B8B4D5903B85055620603"), | ||
("abc", "BA7816BF8F01CFEA414140DE5DAE2223B00361A396177A9CB410FF61F20015AD"), | ||
("abcd", "88D4266FD4E6338D13B845FCF289579D209C897823B9217DA3E161936F031589"), | ||
("abcde", "36BBE50ED96841D10443BCB670D6554F0A34B761BE67EC9C4A8AD2C0C44CA42C"), | ||
("abcdef", "BEF57EC7F53A6D40BEB640A780A639C83BC29AC8A9816F1FC6C5C6DCD93C4721"), | ||
("abcdefg", "7D1A54127B222502F5B79B5FB0803061152A44F92B37E23C6527BAF665D4DA9A"), | ||
("abcdefgh", "9C56CC51B374C3BA189210D5B6D4BF57790D351C96C47C02190ECF1E430635AB"), | ||
("abcdefghi", "19CC02F26DF43CC571BC9ED7B0C4D29224A3EC229529221725EF76D021C8326F"), | ||
("abcdefghij", "72399361DA6A7754FEC986DCA5B7CBAF1C810A28DED4ABAF56B2106D06CB78B0"), | ||
].vals()) { | ||
assert(Hex.encode(SHA256.sum256(Blob.toArray(Text.encodeUtf8(v.0)))) == v.1); | ||
}; | ||
|
||
do { | ||
let h = SHA256.New(); | ||
h.write(Blob.toArray(Text.encodeUtf8("hello"))); | ||
h.write(Blob.toArray(Text.encodeUtf8(" "))); | ||
h.write(Blob.toArray(Text.encodeUtf8("world"))); | ||
assert(Hex.encode(h.sum([])) == "B94D27B9934D3E08A52E52D7DA7DABFAC484EFE37A5380EE9088F7ACE2EFCDE9"); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import Array "mo:base/Array"; | ||
import Iter "mo:base/Iter"; | ||
|
||
import Util "../src/Utilities"; | ||
|
||
let fifty = Iter.toArray(Iter.range(0, 49)); | ||
let hundred = Iter.toArray(Iter.range(0, 99)); | ||
|
||
// Remove the first 50. | ||
assert(Util.removeN(50, hundred) == Iter.toArray(Iter.range(50, 99))); | ||
|
||
// Take the first 50. | ||
assert(Util.takeN(50, hundred) == fifty); | ||
|
||
// Copy the first 50 starting at position 50. | ||
let copyTo = Array.thaw<Nat>(hundred); | ||
assert(Util.copy(50, copyTo, Util.takeN(50, hundred)) == 50); | ||
assert(Array.freeze(copyTo) == Array.append(fifty, fifty)); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
{ | ||
dependencies = [ "base", "encoding" ], | ||
compiler = Some "0.6.10" | ||
} |