• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

moonbitlang / x / 301

10 Dec 2024 06:19AM UTC coverage: 85.204% (-2.6%) from 87.841%
301

Pull #78

github

web-flow
Merge b830031f4 into 91f0fdf48
Pull Request #78: feat: new package encoding

105 of 161 new or added lines in 3 files covered. (65.22%)

124 existing lines in 29 files now uncovered.

1169 of 1372 relevant lines covered (85.2%)

434.92 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

96.3
/crypto/sha256.mbt
1
// Copyright 2024 International Digital Economy Academy
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
//     http://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14

15
///|
16
struct Sha256Context {
17
  reg : FixedArray[UInt] // register A B C D E F G H. i.e. digest
18
  mut len : UInt64
19
  mut buf : Bytes
20
  mut buf_index : Int
21
}
22

23
///| Instantiate a Sha256 context
24
/// `reg` is the initial hash value. Defaults to Sha256's.
25
pub fn Sha256Context::new(
26
  reg~ : FixedArray[UInt] = [
27
    0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab,
28
    0x5be0cd19,
29
  ]
30
) -> Sha256Context {
31
  { reg, len: 0, buf: Bytes::new(64), buf_index: 0 }
23✔
32
}
33

34
///|
35
let sha256_t : FixedArray[UInt] = [ // pre calculated
36
  0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4,
37
  0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe,
38
  0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f,
39
  0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
40
  0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc,
41
  0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b,
42
  0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, 0x19a4c116,
43
  0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
44
  0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7,
45
  0xc67178f2,
46
]
47

48
///|
49
fn pad(self : Sha256Context) -> Bytes {
50
  let mut cnt = self.buf_index
23✔
51
  self.len += 8UL * cnt.to_uint64()
52
  self.buf[cnt] = b'\x80'
53
  cnt += 1
54
  if cnt > 56 {
55
    let temp_arr = Bytes::new(128)
4✔
56
    temp_arr.blit(0, self.buf, 0, cnt)
57
    self.buf = temp_arr
58
  }
59
  while cnt % 64 != 56 {
1,065✔
60
    self.buf[cnt] = b'\x00'
1,042✔
61
    cnt += 1
62
  }
63
  self.buf[cnt] = (self.len >> 56).to_byte()
64
  self.buf[cnt + 1] = (self.len >> 48).to_byte()
65
  self.buf[cnt + 2] = (self.len >> 40).to_byte()
66
  self.buf[cnt + 3] = (self.len >> 32).to_byte()
67
  self.buf[cnt + 4] = (self.len >> 24).to_byte()
68
  self.buf[cnt + 5] = (self.len >> 16).to_byte()
69
  self.buf[cnt + 6] = (self.len >> 8).to_byte()
70
  self.buf[cnt + 7] = (self.len >> 0).to_byte()
71
  return self.buf
72
}
73

74
///|
75
fn transform(
76
  self : Sha256Context,
77
  data : Bytes,
78
  offset~ : Int = 0
79
) -> FixedArray[UInt] {
80
  let w = FixedArray::make(64, 0U)
63✔
81
  let mut a = self.reg[0]
82
  let mut b = self.reg[1]
83
  let mut c = self.reg[2]
84
  let mut d = self.reg[3]
85
  let mut e = self.reg[4]
86
  let mut f = self.reg[5]
87
  let mut g = self.reg[6]
88
  let mut h = self.reg[7]
89
  for index = 0; index < 16; index = index + 1 {
1,008✔
90
    w[index] = bytes_u8_to_u32be(data, i=4 * index + offset)
1,008✔
91
  }
92
  for index = 16; index < 64; index = index + 1 {
3,024✔
93
    let sigma_0 = rotate_right_u(w[index - 15], 7) ^
3,024✔
94
      rotate_right_u(w[index - 15], 18) ^
95
      (w[index - 15] >> 3)
96
    let sigma_1 = rotate_right_u(w[index - 2], 17) ^
97
      rotate_right_u(w[index - 2], 19) ^
98
      (w[index - 2] >> 10)
99
    w[index] = w[index - 16] + sigma_0 + w[index - 7] + sigma_1
100
  }
101
  for index = 0; index < 64; index = index + 1 {
4,032✔
102
    let big_sigma_1 = rotate_right_u(e, 6) ^
4,032✔
103
      rotate_right_u(e, 11) ^
104
      rotate_right_u(e, 25)
105
    let t_1 = h + big_sigma_1 + gg_1(e, f, g) + sha256_t[index] + w[index]
106
    let big_sigma_0 = rotate_right_u(a, 2) ^
107
      rotate_right_u(a, 13) ^
108
      rotate_right_u(a, 22)
109
    let t_2 = big_sigma_0 + ff_1(a, b, c)
110
    h = g
111
    g = f
112
    f = e
113
    e = d + t_1
114
    d = c
115
    c = b
116
    b = a
117
    a = t_1 + t_2
118
  }
119
  self.reg[0] += a
120
  self.reg[1] += b
121
  self.reg[2] += c
122
  self.reg[3] += d
123
  self.reg[4] += e
124
  self.reg[5] += f
125
  self.reg[6] += g
126
  self.reg[7] += h
127
  self.reg
128
}
129

130
///|
131
pub fn update_from_iter(self : Sha256Context, data : Iter[Byte]) -> Unit {
132
  data.each(
39✔
133
    fn(b) {
134
      self.buf[self.buf_index] = b
64✔
135
      self.buf_index += 1
136
      if self.buf_index == 64 {
137
        self.buf_index = 0
1✔
138
        self.len += 512UL
139
        let _ = self.transform(self.buf)
140

141
      }
142
    },
143
  )
144
}
145

146
///| update the state of given context from new `data` 
147
pub fn update(self : Sha256Context, data : Bytes) -> Unit {
148
  let mut offset = 0
87✔
149
  while offset < data.length() {
204✔
150
    let min_len = if 64 - self.buf_index >= data.length() - offset {
117✔
151
      data.length() - offset
85✔
152
    } else {
153
      64 - self.buf_index
32✔
154
    }
155
    self.buf.blit(self.buf_index, data, offset, min_len)
156
    self.buf_index += min_len
157
    if self.buf_index == 64 {
158
      self.len += 512UL
35✔
159
      self.buf_index = 0
160
      let _ = self.transform(self.buf)
161

162
    }
163
    offset += min_len
164
  }
165
}
166

167
///|
168
fn sha256_compute(
169
  self : Sha256Context,
170
  data~ : Iter[Byte] = Iter::empty()
171
) -> FixedArray[UInt] {
172
  self.update_from_iter(data)
23✔
173
  let msg = self.pad()
174
  if msg.length() > 64 {
175
    let _ = self.transform(msg)
4✔
176
    self.transform(msg, offset=64)
177
  } else {
178
    self.transform(msg)
19✔
179
  }
180
}
181

182
///| Compute the Sha256 digest from given Sha256Context
183
pub fn finalize(self : Sha256Context) -> Bytes {
184
  arr_u32_to_u8be(self.sha256_compute().iter(), 256)
3✔
185
}
186

187
///| Compute the Sha256 digest in `Bytes` of some `data`. Note that Sha256 is big-endian.
188
pub fn sha256(data : Bytes) -> Bytes {
189
  let ctx = Sha256Context::new()
8✔
190
  let _ = ctx.update(data)
191
  arr_u32_to_u8be(ctx.sha256_compute().iter(), 256)
192
}
193

194
///|
195
pub fn sha256_from_iter(data : Iter[Byte]) -> Bytes {
UNCOV
196
  let ctx = Sha256Context::new()
×
197
  let _ = ctx.update_from_iter(data)
198
  arr_u32_to_u8be(ctx.sha256_compute().iter(), 256)
199
}
200

201
test {
202
  // Sha256
203
  fn sha256_u32(data : Bytes) -> FixedArray[UInt] {
204
    let ctx = Sha256Context::new()
205
    let _ = ctx.update(data)
206
    ctx.sha256_compute()
207
  }
208

209
  inspect!(
210
    uints_to_hex_string(
211
      sha256_u32(
212
        b"\x61\x62\x63", // abc in utf-8
213
      ).iter(),
214
    ),
215
    content="ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad",
216
  )
217
  inspect!(
218
    uints_to_hex_string(
219
      sha256_u32(
220
        // abcd * 16 in utf-8
221
        b"\x61\x62\x63\x64\x61\x62\x63\x64\x61\x62\x63\x64\x61\x62\x63\x64\x61\x62\x63\x64\x61\x62\x63\x64\x61\x62\x63\x64\x61\x62\x63\x64\x61\x62\x63\x64\x61\x62\x63\x64\x61\x62\x63\x64\x61\x62\x63\x64\x61\x62\x63\x64\x61\x62\x63\x64\x61\x62\x63\x64\x61\x62\x63\x64",
222
      ).iter(),
223
    ),
224
    content="625b41490b883891943c5fa54ad45d7c900b9b6e91e159334e320b1f5215a209",
225
  )
226
  assert_eq!(
227
    bytes_to_hex_string(sha256(b"\x61\x62\x63")),
228
    uints_to_hex_string(sha256_u32(b"\x61\x62\x63").iter()),
229
  )
230
  let hash1 = "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
231
  let ctx = Sha256Context::new()
232
  ctx.update(b"\x61")
233
  ctx.update(b"\x62")
234
  ctx.update(b"\x63")
235
  assert_eq!(hash1, bytes_to_hex_string(ctx.finalize()))
236
  let ctx = Sha256Context::new()
237
  let data = b"\x61\x62\x63\x64\x61\x62\x63\x64\x61\x62\x63\x64\x61\x62\x63\x64\x61\x62\x63\x64\x61\x62\x63\x64\x61\x62\x63\x64\x61\x62\x63\x64\x61\x62\x63\x64\x61\x62\x63\x64\x61\x62\x63\x64\x61\x62\x63\x64\x61\x62\x63\x64\x61\x62\x63\x64\x61\x62\x63\x64\x61\x62\x63\x64"
238
  for i = 0; i < data.length(); i = i + 1 {
239
    ctx.update(Bytes::make(1, data[i]))
240
  }
241
  assert_eq!(
242
    bytes_to_hex_string(ctx.finalize()),
243
    "625b41490b883891943c5fa54ad45d7c900b9b6e91e159334e320b1f5215a209",
244
  )
245
  let ctx = Sha256Context::new()
246
  for i = 0; i < data.length(); i = i + 4 {
247
    ctx.update_from_iter(b"\x61\x62\x63\x64".iter())
248
  }
249
  assert_eq!(
250
    bytes_to_hex_string(ctx.finalize()),
251
    "625b41490b883891943c5fa54ad45d7c900b9b6e91e159334e320b1f5215a209",
252
  )
253
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc