(index<- )        ./librustc/util/sha2.rs

    git branch:    * master           5200215 auto merge of #14035 : alexcrichton/rust/experimental, r=huonw
    modified:    Fri May  9 13:02:28 2014
   1  // Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
   2  // file at the top-level directory of this distribution and at
   3  // http://rust-lang.org/COPYRIGHT.
   4  //
   5  // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
   6  // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
   7  // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
   8  // option. This file may not be copied, modified, or distributed
   9  // except according to those terms.
  10  
  11  //! This module implements only the Sha256 function since that is all that is needed for internal
  12  //! use. This implementation is not intended for external use or for any use where security is
  13  //! important.
  14  
  15  use std::iter::range_step;
  16  use std::num::Zero;
  17  use std::slice::bytes::{MutableByteVector, copy_memory};
  18  use serialize::hex::ToHex;
  19  
  20  /// Write a u32 into a vector, which must be 4 bytes long. The value is written in big-endian
  21  /// format.
  22  fn write_u32_be(dst: &mut[u8], input: u32) {
  23      use std::mem::to_be32;
  24      assert!(dst.len() == 4);
  25      unsafe {
  26          let x = dst.unsafe_mut_ref(0) as *mut _ as *mut u32;
  27          *x = to_be32(input);
  28      }
  29  }
  30  
  31  /// Read a vector of bytes into a vector of u32s. The values are read in big-endian format.
  32  fn read_u32v_be(dst: &mut[u32], input: &[u8]) {
  33      use std::mem::to_be32;
  34      assert!(dst.len() * 4 == input.len());
  35      unsafe {
  36          let mut x = dst.unsafe_mut_ref(0) as *mut _ as *mut u32;
  37          let mut y = input.unsafe_ref(0) as *_ as *u32;
  38          for _ in range(0, dst.len()) {
  39              *x = to_be32(*y);
  40              x = x.offset(1);
  41              y = y.offset(1);
  42          }
  43      }
  44  }
  45  
  46  trait ToBits {
  47      /// Convert the value in bytes to the number of bits, a tuple where the 1st item is the
  48      /// high-order value and the 2nd item is the low order value.
  49      fn to_bits(self) -> (Self, Self);
  50  }
  51  
  52  impl ToBits for u64 {
  53      fn to_bits(self) -> (u64, u64) {
  54          return (self >> 61, self << 3);
  55      }
  56  }
  57  
  58  /// Adds the specified number of bytes to the bit count. fail!() if this would cause numeric
  59  /// overflow.
  60  fn add_bytes_to_bits<T: Int + CheckedAdd + ToBits>(bitsT, bytesT) -> T {
  61      let (new_high_bits, new_low_bits) = bytes.to_bits();
  62  
  63      if new_high_bits > Zero::zero() {
  64          fail!("numeric overflow occured.")
  65      }
  66  
  67      match bits.checked_add(&new_low_bits) {
  68          Some(x) => return x,
  69          None => fail!("numeric overflow occured.")
  70      }
  71  }
  72  
  73  /// A FixedBuffer, likes its name implies, is a fixed size buffer. When the buffer becomes full, it
  74  /// must be processed. The input() method takes care of processing and then clearing the buffer
  75  /// automatically. However, other methods do not and require the caller to process the buffer. Any
  76  /// method that modifies the buffer directory or provides the caller with bytes that can be modified
  77  /// results in those bytes being marked as used by the buffer.
  78  trait FixedBuffer {
  79      /// Input a vector of bytes. If the buffer becomes full, process it with the provided
  80      /// function and then clear the buffer.
  81      fn input(&mut self, input: &[u8], func: |&[u8]|);
  82  
  83      /// Reset the buffer.
  84      fn reset(&mut self);
  85  
  86      /// Zero the buffer up until the specified index. The buffer position currently must not be
  87      /// greater than that index.
  88      fn zero_until(&mut self, idx: uint);
  89  
  90      /// Get a slice of the buffer of the specified size. There must be at least that many bytes
  91      /// remaining in the buffer.
  92      fn next<'s>(&'s mut self, len: uint) -> &'s mut [u8];
  93  
  94      /// Get the current buffer. The buffer must already be full. This clears the buffer as well.
  95      fn full_buffer<'s>(&'s mut self) -> &'s [u8];
  96  
  97      /// Get the current position of the buffer.
  98      fn position(&self) -> uint;
  99  
 100      /// Get the number of bytes remaining in the buffer until it is full.
 101      fn remaining(&self) -> uint;
 102  
 103      /// Get the size of the buffer
 104      fn size(&self) -> uint;
 105  }
 106  
 107  /// A FixedBuffer of 64 bytes useful for implementing Sha256 which has a 64 byte blocksize.
 108  struct FixedBuffer64 {
 109      buffer: [u8, ..64],
 110      buffer_idx: uint,
 111  }
 112  
 113  impl FixedBuffer64 {
 114      /// Create a new FixedBuffer64
 115      fn new() -> FixedBuffer64 {
 116          return FixedBuffer64 {
 117              buffer: [0u8, ..64],
 118              buffer_idx: 0
 119          };
 120      }
 121  }
 122  
 123  impl FixedBuffer for FixedBuffer64 {
 124      fn input(&mut self, input&[u8], func|&[u8]|) {
 125          let mut i = 0;
 126  
 127          let size = self.size();
 128  
 129          // If there is already data in the buffer, copy as much as we can into it and process
 130          // the data if the buffer becomes full.
 131          if self.buffer_idx != 0 {
 132              let buffer_remaining = size - self.buffer_idx;
 133              if input.len() >= buffer_remaining {
 134                      copy_memory(
 135                          self.buffer.mut_slice(self.buffer_idx, size),
 136                          input.slice_to(buffer_remaining));
 137                  self.buffer_idx = 0;
 138                  func(self.buffer);
 139                  i += buffer_remaining;
 140              } else {
 141                  copy_memory(
 142                      self.buffer.mut_slice(self.buffer_idx, self.buffer_idx + input.len()),
 143                      input);
 144                  self.buffer_idx += input.len();
 145                  return;
 146              }
 147          }
 148  
 149          // While we have at least a full buffer size chunk's worth of data, process that data
 150          // without copying it into the buffer
 151          while input.len() - i >= size {
 152              func(input.slice(i, i + size));
 153              i += size;
 154          }
 155  
 156          // Copy any input data into the buffer. At this point in the method, the amount of
 157          // data left in the input vector will be less than the buffer size and the buffer will
 158          // be empty.
 159          let input_remaining = input.len() - i;
 160          copy_memory(
 161              self.buffer.mut_slice(0, input_remaining),
 162              input.slice_from(i));
 163          self.buffer_idx += input_remaining;
 164      }
 165  
 166      fn reset(&mut self) {
 167          self.buffer_idx = 0;
 168      }
 169  
 170      fn zero_until(&mut self, idxuint) {
 171          assert!(idx >= self.buffer_idx);
 172          self.buffer.mut_slice(self.buffer_idx, idx).set_memory(0);
 173          self.buffer_idx = idx;
 174      }
 175  
 176      fn next<'s>(&'s mut self, lenuint) -> &'s mut [u8] {
 177          self.buffer_idx += len;
 178          return self.buffer.mut_slice(self.buffer_idx - len, self.buffer_idx);
 179      }
 180  
 181      fn full_buffer<'s>(&'s mut self) -> &'s [u8] {
 182          assert!(self.buffer_idx == 64);
 183          self.buffer_idx = 0;
 184          return self.buffer.slice_to(64);
 185      }
 186  
 187      fn position(&self) -> uint { self.buffer_idx }
 188  
 189      fn remaining(&self) -> uint { 64 - self.buffer_idx }
 190  
 191      fn size(&self) -> uint { 64 }
 192  }
 193  
 194  /// The StandardPadding trait adds a method useful for Sha256 to a FixedBuffer struct.
 195  trait StandardPadding {
 196      /// Add padding to the buffer. The buffer must not be full when this method is called and is
 197      /// guaranteed to have exactly rem remaining bytes when it returns. If there are not at least
 198      /// rem bytes available, the buffer will be zero padded, processed, cleared, and then filled
 199      /// with zeros again until only rem bytes are remaining.
 200      fn standard_padding(&mut self, rem: uint, func: |&[u8]|);
 201  }
 202  
 203  impl <T: FixedBuffer> StandardPadding for T {
 204      fn standard_padding(&mut self, remuint, func|&[u8]|) {
 205          let size = self.size();
 206  
 207          self.next(1)[0] = 128;
 208  
 209          if self.remaining() < rem {
 210              self.zero_until(size);
 211              func(self.full_buffer());
 212          }
 213  
 214          self.zero_until(size - rem);
 215      }
 216  }
 217  
 218  /// The Digest trait specifies an interface common to digest functions, such as SHA-1 and the SHA-2
 219  /// family of digest functions.
 220  pub trait Digest {
 221      /// Provide message data.
 222      ///
 223      /// # Arguments
 224      ///
 225      /// * input - A vector of message data
 226      fn input(&mut self, input: &[u8]);
 227  
 228      /// Retrieve the digest result. This method may be called multiple times.
 229      ///
 230      /// # Arguments
 231      ///
 232      /// * out - the vector to hold the result. Must be large enough to contain output_bits().
 233      fn result(&mut self, out: &mut [u8]);
 234  
 235      /// Reset the digest. This method must be called after result() and before supplying more
 236      /// data.
 237      fn reset(&mut self);
 238  
 239      /// Get the output size in bits.
 240      fn output_bits(&self) -> uint;
 241  
 242      /// Convenience function that feeds a string into a digest.
 243      ///
 244      /// # Arguments
 245      ///
 246      /// * `input` The string to feed into the digest
 247      fn input_str(&mut self, input&str) {
 248          self.input(input.as_bytes());
 249      }
 250  
 251      /// Convenience function that retrieves the result of a digest as a
 252      /// newly allocated vec of bytes.
 253      fn result_bytes(&mut self) -> Vec<u8> {
 254          let mut buf = Vec::from_elem((self.output_bits()+7)/8, 0u8);
 255          self.result(buf.as_mut_slice());
 256          buf
 257      }
 258  
 259      /// Convenience function that retrieves the result of a digest as a
 260      /// ~str in hexadecimal format.
 261      fn result_str(&mut self) -> ~str {
 262          self.result_bytes().as_slice().to_hex()
 263      }
 264  }
 265  
 266  // A structure that represents that state of a digest computation for the SHA-2 512 family of digest
 267  // functions
 268  struct Engine256State {
 269      h0: u32,
 270      h1: u32,
 271      h2: u32,
 272      h3: u32,
 273      h4: u32,
 274      h5: u32,
 275      h6: u32,
 276      h7: u32,
 277  }
 278  
 279  impl Engine256State {
 280      fn new(h&[u32, ..8]) -> Engine256State {
 281          return Engine256State {
 282              h0: h[0],
 283              h1: h[1],
 284              h2: h[2],
 285              h3: h[3],
 286              h4: h[4],
 287              h5: h[5],
 288              h6: h[6],
 289              h7: h[7]
 290          };
 291      }
 292  
 293      fn reset(&mut self, h&[u32, ..8]) {
 294          self.h0 = h[0];
 295          self.h1 = h[1];
 296          self.h2 = h[2];
 297          self.h3 = h[3];
 298          self.h4 = h[4];
 299          self.h5 = h[5];
 300          self.h6 = h[6];
 301          self.h7 = h[7];
 302      }
 303  
 304      fn process_block(&mut self, data&[u8]) {
 305          fn ch(xu32, yu32, zu32) -> u32 {
 306              ((x & y) ^ ((!x) & z))
 307          }
 308  
 309          fn maj(xu32, yu32, zu32) -> u32 {
 310              ((x & y) ^ (x & z) ^ (y & z))
 311          }
 312  
 313          fn sum0(xu32) -> u32 {
 314              ((x >> 2) | (x << 30)) ^ ((x >> 13) | (x << 19)) ^ ((x >> 22) | (x << 10))
 315          }
 316  
 317          fn sum1(xu32) -> u32 {
 318              ((x >> 6) | (x << 26)) ^ ((x >> 11) | (x << 21)) ^ ((x >> 25) | (x << 7))
 319          }
 320  
 321          fn sigma0(x: u32) -> u32 {
 322              ((x >> 7) | (x << 25)) ^ ((x >> 18) | (x << 14)) ^ (x >> 3)
 323          }
 324  
 325          fn sigma1(x: u32) -> u32 {
 326              ((x >> 17) | (x << 15)) ^ ((x >> 19) | (x << 13)) ^ (x >> 10)
 327          }
 328  
 329          let mut a = self.h0;
 330          let mut b = self.h1;
 331          let mut c = self.h2;
 332          let mut d = self.h3;
 333          let mut e = self.h4;
 334          let mut f = self.h5;
 335          let mut g = self.h6;
 336          let mut h = self.h7;
 337  
 338          let mut w = [0u32, ..64];
 339  
 340          // Sha-512 and Sha-256 use basically the same calculations which are implemented
 341          // by these macros. Inlining the calculations seems to result in better generated code.
 342          macro_rules! schedule_round( ($t:expr) => (
 343                  w[$t] = sigma1(w[$t - 2]) + w[$t - 7] + sigma0(w[$t - 15]) + w[$t - 16];
 344                  )
 345          )
 346  
 347          macro_rules! sha2_round(
 348              ($A:ident, $B:ident, $C:ident, $D:ident,
 349               $E:ident, $F:ident, $G:ident, $H:ident, $K:ident, $t:expr) => (
 350                  {
 351                      $H += sum1($E) + ch($E, $F, $G) + $K[$t] + w[$t];
 352                      $D += $H;
 353                      $H += sum0($A) + maj($A, $B, $C);
 354                  }
 355               )
 356          )
 357  
 358          read_u32v_be(w.mut_slice(0, 16), data);
 359  
 360          // Putting the message schedule inside the same loop as the round calculations allows for
 361          // the compiler to generate better code.
 362          for t in range_step(0u, 48, 8) {
 363              schedule_round!(t + 16);
 364              schedule_round!(t + 17);
 365              schedule_round!(t + 18);
 366              schedule_round!(t + 19);
 367              schedule_round!(t + 20);
 368              schedule_round!(t + 21);
 369              schedule_round!(t + 22);
 370              schedule_round!(t + 23);
 371  
 372              sha2_round!(a, b, c, d, e, f, g, h, K32, t);
 373              sha2_round!(h, a, b, c, d, e, f, g, K32, t + 1);
 374              sha2_round!(g, h, a, b, c, d, e, f, K32, t + 2);
 375              sha2_round!(f, g, h, a, b, c, d, e, K32, t + 3);
 376              sha2_round!(e, f, g, h, a, b, c, d, K32, t + 4);
 377              sha2_round!(d, e, f, g, h, a, b, c, K32, t + 5);
 378              sha2_round!(c, d, e, f, g, h, a, b, K32, t + 6);
 379              sha2_round!(b, c, d, e, f, g, h, a, K32, t + 7);
 380          }
 381  
 382          for t in range_step(48u, 64, 8) {
 383              sha2_round!(a, b, c, d, e, f, g, h, K32, t);
 384              sha2_round!(h, a, b, c, d, e, f, g, K32, t + 1);
 385              sha2_round!(g, h, a, b, c, d, e, f, K32, t + 2);
 386              sha2_round!(f, g, h, a, b, c, d, e, K32, t + 3);
 387              sha2_round!(e, f, g, h, a, b, c, d, K32, t + 4);
 388              sha2_round!(d, e, f, g, h, a, b, c, K32, t + 5);
 389              sha2_round!(c, d, e, f, g, h, a, b, K32, t + 6);
 390              sha2_round!(b, c, d, e, f, g, h, a, K32, t + 7);
 391          }
 392  
 393          self.h0 += a;
 394          self.h1 += b;
 395          self.h2 += c;
 396          self.h3 += d;
 397          self.h4 += e;
 398          self.h5 += f;
 399          self.h6 += g;
 400          self.h7 += h;
 401      }
 402  }
 403  
 404  static K32: [u32, ..64] = [
 405      0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
 406      0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
 407      0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
 408      0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
 409      0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
 410      0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
 411      0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
 412      0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
 413      0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
 414      0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
 415      0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
 416      0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
 417      0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
 418      0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
 419      0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
 420      0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
 421  ];
 422  
 423  // A structure that keeps track of the state of the Sha-256 operation and contains the logic
 424  // necessary to perform the final calculations.
 425  struct Engine256 {
 426      length_bits: u64,
 427      buffer: FixedBuffer64,
 428      state: Engine256State,
 429      finished: bool,
 430  }
 431  
 432  impl Engine256 {
 433      fn new(h&[u32, ..8]) -> Engine256 {
 434          return Engine256 {
 435              length_bits: 0,
 436              buffer: FixedBuffer64::new(),
 437              state: Engine256State::new(h),
 438              finished: false
 439          }
 440      }
 441  
 442      fn reset(&mut self, h&[u32, ..8]) {
 443          self.length_bits = 0;
 444          self.buffer.reset();
 445          self.state.reset(h);
 446          self.finished = false;
 447      }
 448  
 449      fn input(&mut self, input&[u8]) {
 450          assert!(!self.finished)
 451          // Assumes that input.len() can be converted to u64 without overflow
 452          self.length_bits = add_bytes_to_bits(self.length_bits, input.len() as u64);
 453          let self_state = &mut self.state;
 454          self.buffer.input(input, |input&[u8]{ self_state.process_block(input) });
 455      }
 456  
 457      fn finish(&mut self) {
 458          if self.finished {
 459              return;
 460          }
 461  
 462          let self_state = &mut self.state;
 463          self.buffer.standard_padding(8, |input&[u8]{ self_state.process_block(input) });
 464          write_u32_be(self.buffer.next(4), (self.length_bits >> 32) as u32 );
 465          write_u32_be(self.buffer.next(4), self.length_bits as u32);
 466          self_state.process_block(self.buffer.full_buffer());
 467  
 468          self.finished = true;
 469      }
 470  }
 471  
 472  /// The SHA-256 hash algorithm
 473  pub struct Sha256 {
 474      engine: Engine256
 475  }
 476  
 477  impl Sha256 {
 478      /// Construct a new instance of a SHA-256 digest.
 479      pub fn new() -> Sha256 {
 480          Sha256 {
 481              engine: Engine256::new(&H256)
 482          }
 483      }
 484  }
 485  
 486  impl Digest for Sha256 {
 487      fn input(&mut self, d&[u8]) {
 488          self.engine.input(d);
 489      }
 490  
 491      fn result(&mut self, out&mut [u8]) {
 492          self.engine.finish();
 493  
 494          write_u32_be(out.mut_slice(0, 4), self.engine.state.h0);
 495          write_u32_be(out.mut_slice(4, 8), self.engine.state.h1);
 496          write_u32_be(out.mut_slice(8, 12), self.engine.state.h2);
 497          write_u32_be(out.mut_slice(12, 16), self.engine.state.h3);
 498          write_u32_be(out.mut_slice(16, 20), self.engine.state.h4);
 499          write_u32_be(out.mut_slice(20, 24), self.engine.state.h5);
 500          write_u32_be(out.mut_slice(24, 28), self.engine.state.h6);
 501          write_u32_be(out.mut_slice(28, 32), self.engine.state.h7);
 502      }
 503  
 504      fn reset(&mut self) {
 505          self.engine.reset(&H256);
 506      }
 507  
 508      fn output_bits(&self) -> uint { 256 }
 509  }
 510  
 511  static H256: [u32, ..8] = [
 512      0x6a09e667,
 513      0xbb67ae85,
 514      0x3c6ef372,
 515      0xa54ff53a,
 516      0x510e527f,
 517      0x9b05688c,
 518      0x1f83d9ab,
 519      0x5be0cd19
 520  ];
 521  
 522  #[cfg(test)]
 523  mod tests {
 524      extern crate rand;
 525  
 526      use super::{Digest, Sha256, FixedBuffer};
 527      use std::num::Bounded;
 528      use self::rand::isaac::IsaacRng;
 529      use self::rand::Rng;
 530      use serialize::hex::FromHex;
 531  
 532      // A normal addition - no overflow occurs
 533      #[test]
 534      fn test_add_bytes_to_bits_ok() {
 535          assert!(super::add_bytes_to_bits::<u64>(100, 10) == 180);
 536      }
 537  
 538      // A simple failure case - adding 1 to the max value
 539      #[test]
 540      #[should_fail]
 541      fn test_add_bytes_to_bits_overflow() {
 542          super::add_bytes_to_bits::<u64>(Bounded::max_value(), 1);
 543      }
 544  
 545      struct Test {
 546          input: ~str,
 547          output_str: ~str,
 548      }
 549  
 550      fn test_hash<D: Digest>(sh: &mut D, tests: &[Test]) {
 551          // Test that it works when accepting the message all at once
 552          for t in tests.iter() {
 553              sh.reset();
 554              sh.input_str(t.input);
 555              let out_str = sh.result_str();
 556              assert!(out_str == t.output_str);
 557          }
 558  
 559          // Test that it works when accepting the message in pieces
 560          for t in tests.iter() {
 561              sh.reset();
 562              let len = t.input.len();
 563              let mut left = len;
 564              while left > 0u {
 565                  let take = (left + 1u) / 2u;
 566                  sh.input_str(t.input.slice(len - left, take + len - left));
 567                  left = left - take;
 568              }
 569              let out_str = sh.result_str();
 570              assert!(out_str == t.output_str);
 571          }
 572      }
 573  
 574      #[test]
 575      fn test_sha256() {
 576          // Examples from wikipedia
 577          let wikipedia_tests = vec!(
 578              Test {
 579                  input: "".to_owned(),
 580                  output_str: "e3b0c44298fc1c149afb\
 581              f4c8996fb92427ae41e4649b934ca495991b7852b855".to_owned()
 582              },
 583              Test {
 584                  input: "The quick brown fox jumps over the lazy dog".to_owned(),
 585                  output_str: "d7a8fbb307d7809469ca\
 586              9abcb0082e4f8d5651e46d3cdb762d02d0bf37c9e592".to_owned()
 587              },
 588              Test {
 589                  input: "The quick brown fox jumps over the lazy dog.".to_owned(),
 590                  output_str: "ef537f25c895bfa78252\
 591              6529a9b63d97aa631564d5d789c2b765448c8635fb6c".to_owned()
 592              });
 593  
 594          let tests = wikipedia_tests;
 595  
 596          let mut sh = box Sha256::new();
 597  
 598          test_hash(sh, tests.as_slice());
 599      }
 600  
 601      /// Feed 1,000,000 'a's into the digest with varying input sizes and check that the result is
 602      /// correct.
 603      fn test_digest_1million_random<D: Digest>(digest: &mut D, blocksize: uint, expected: &str) {
 604          let total_size = 1000000;
 605          let buffer = Vec::from_elem(blocksize * 2, 'a' as u8);
 606          let mut rng = IsaacRng::new_unseeded();
 607          let mut count = 0;
 608  
 609          digest.reset();
 610  
 611          while count < total_size {
 612              let next: uint = rng.gen_range(0, 2 * blocksize + 1);
 613              let remaining = total_size - count;
 614              let size = if next > remaining { remaining } else { next };
 615              digest.input(buffer.slice_to(size));
 616              count += size;
 617          }
 618  
 619          let result_str = digest.result_str();
 620          let result_bytes = digest.result_bytes();
 621  
 622          assert_eq!(expected, result_str.as_slice());
 623  
 624          let expected_vec: Vec<u8> = expected.from_hex()
 625                                              .unwrap()
 626                                              .move_iter()
 627                                              .collect();
 628          assert_eq!(expected_vec, result_bytes);
 629      }
 630  
 631      #[test]
 632      fn test_1million_random_sha256() {
 633          let mut sh = Sha256::new();
 634          test_digest_1million_random(
 635              &mut sh,
 636              64,
 637              "cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0");
 638      }
 639  }
 640  
 641  #[cfg(test)]
 642  mod bench {
 643      extern crate test;
 644      use self::test::Bencher;
 645      use super::{Sha256, FixedBuffer, Digest};
 646  
 647      #[bench]
 648      pub fn sha256_10(b: &mut Bencher) {
 649          let mut sh = Sha256::new();
 650          let bytes = [1u8, ..10];
 651          b.iter(|| {
 652              sh.input(bytes);
 653          });
 654          b.bytes = bytes.len() as u64;
 655      }
 656  
 657      #[bench]
 658      pub fn sha256_1k(b: &mut Bencher) {
 659          let mut sh = Sha256::new();
 660          let bytes = [1u8, ..1024];
 661          b.iter(|| {
 662              sh.input(bytes);
 663          });
 664          b.bytes = bytes.len() as u64;
 665      }
 666  
 667      #[bench]
 668      pub fn sha256_64k(b: &mut Bencher) {
 669          let mut sh = Sha256::new();
 670          let bytes = [1u8, ..65536];
 671          b.iter(|| {
 672              sh.input(bytes);
 673          });
 674          b.bytes = bytes.len() as u64;
 675      }
 676  }


librustc/util/sha2.rs:321:8-321:8 -fn- definition:
        fn sigma0(x: u32) -> u32 {
            ((x >> 7) | (x << 25)) ^ ((x >> 18) | (x << 14)) ^ (x >> 3)
        }
references:- 8
342:         macro_rules! schedule_round( ($t:expr) => (
343:                 w[$t] = sigma1(w[$t - 2]) + w[$t - 7] + sigma0(w[$t - 15]) + w[$t - 16];
344:                 )


librustc/util/sha2.rs:309:8-309:8 -fn- definition:
        fn maj(x: u32, y: u32, z: u32) -> u32 {
            ((x & y) ^ (x & z) ^ (y & z))
        }
references:- 16
352:                     $D += $H;
353:                     $H += sum0($A) + maj($A, $B, $C);
354:                 }


librustc/util/sha2.rs:313:8-313:8 -fn- definition:
        fn sum0(x: u32) -> u32 {
            ((x >> 2) | (x << 30)) ^ ((x >> 13) | (x << 19)) ^ ((x >> 22) | (x << 10))
        }
references:- 16
352:                     $D += $H;
353:                     $H += sum0($A) + maj($A, $B, $C);
354:                 }


librustc/util/sha2.rs:305:8-305:8 -fn- definition:
        fn ch(x: u32, y: u32, z: u32) -> u32 {
            ((x & y) ^ ((!x) & z))
        }
references:- 16
350:                 {
351:                     $H += sum1($E) + ch($E, $F, $G) + $K[$t] + w[$t];
352:                     $D += $H;


librustc/util/sha2.rs:45:1-45:1 -trait- definition:
trait ToBits {
    /// Convert the value in bytes to the number of bits, a tuple where the 1st item is the
    /// high-order value and the 2nd item is the low order value.
references:- 4
48:     /// high-order value and the 2nd item is the low order value.
49:     fn to_bits(self) -> (Self, Self);
50: }
--
59: /// overflow.
60: fn add_bytes_to_bits<T: Int + CheckedAdd + ToBits>(bits: T, bytes: T) -> T {
61:     let (new_high_bits, new_low_bits) = bytes.to_bits();


librustc/util/sha2.rs:325:8-325:8 -fn- definition:
        fn sigma1(x: u32) -> u32 {
            ((x >> 17) | (x << 15)) ^ ((x >> 19) | (x << 13)) ^ (x >> 10)
        }
references:- 8
342:         macro_rules! schedule_round( ($t:expr) => (
343:                 w[$t] = sigma1(w[$t - 2]) + w[$t - 7] + sigma0(w[$t - 15]) + w[$t - 16];
344:                 )


librustc/util/sha2.rs:21:12-21:12 -fn- definition:
/// format.
fn write_u32_be(dst: &mut[u8], input: u32) {
    use std::mem::to_be32;
references:- 10
495:         write_u32_be(out.mut_slice(4, 8), self.engine.state.h1);
496:         write_u32_be(out.mut_slice(8, 12), self.engine.state.h2);
497:         write_u32_be(out.mut_slice(12, 16), self.engine.state.h3);
498:         write_u32_be(out.mut_slice(16, 20), self.engine.state.h4);
499:         write_u32_be(out.mut_slice(20, 24), self.engine.state.h5);
500:         write_u32_be(out.mut_slice(24, 28), self.engine.state.h6);
501:         write_u32_be(out.mut_slice(28, 32), self.engine.state.h7);
502:     }


librustc/util/sha2.rs:317:8-317:8 -fn- definition:
        fn sum1(x: u32) -> u32 {
            ((x >> 6) | (x << 26)) ^ ((x >> 11) | (x << 21)) ^ ((x >> 25) | (x << 7))
        }
references:- 16
350:                 {
351:                     $H += sum1($E) + ch($E, $F, $G) + $K[$t] + w[$t];
352:                     $D += $H;


librustc/util/sha2.rs:424:48-424:48 -struct- definition:
// necessary to perform the final calculations.
struct Engine256 {
    length_bits: u64,
references:- 4
433:     fn new(h: &[u32, ..8]) -> Engine256 {
434:         return Engine256 {
435:             length_bits: 0,
--
473: pub struct Sha256 {
474:     engine: Engine256
475: }


librustc/util/sha2.rs:77:63-77:63 -trait- definition:
/// results in those bytes being marked as used by the buffer.
trait FixedBuffer {
    /// Input a vector of bytes. If the buffer becomes full, process it with the provided
references:- 2
123: impl FixedBuffer for FixedBuffer64 {
124:     fn input(&mut self, input: &[u8], func: |&[u8]|) {
--
203: impl <T: FixedBuffer> StandardPadding for T {
204:     fn standard_padding(&mut self, rem: uint, func: |&[u8]|) {


librustc/util/sha2.rs:107:92-107:92 -struct- definition:
/// A FixedBuffer of 64 bytes useful for implementing Sha256 which has a 64 byte blocksize.
struct FixedBuffer64 {
    buffer: [u8, ..64],
references:- 5
115:     fn new() -> FixedBuffer64 {
116:         return FixedBuffer64 {
117:             buffer: [0u8, ..64],
--
123: impl FixedBuffer for FixedBuffer64 {
124:     fn input(&mut self, input: &[u8], func: |&[u8]|) {
--
426:     length_bits: u64,
427:     buffer: FixedBuffer64,
428:     state: Engine256State,


librustc/util/sha2.rs:267:13-267:13 -struct- definition:
// functions
struct Engine256State {
    h0: u32,
references:- 4
280:     fn new(h: &[u32, ..8]) -> Engine256State {
281:         return Engine256State {
282:             h0: h[0],
--
427:     buffer: FixedBuffer64,
428:     state: Engine256State,
429:     finished: bool,


librustc/util/sha2.rs:472:31-472:31 -struct- definition:
/// The SHA-256 hash algorithm
pub struct Sha256 {
    engine: Engine256
references:- 8
479:     pub fn new() -> Sha256 {
480:         Sha256 {
481:             engine: Engine256::new(&H256)
--
486: impl Digest for Sha256 {
487:     fn input(&mut self, d: &[u8]) {
librustc/middle/trans/context.rs:
131:                emap2: resolve::ExportMap2,
132:                symbol_hasher: Sha256,
133:                link_meta: LinkMeta,
librustc/back/link.rs:
552: fn truncated_hash_result(symbol_hasher: &mut Sha256) -> ~str {
553:     let output = symbol_hasher.result_bytes();
--
560: fn symbol_hash(tcx: &ty::ctxt,
561:                symbol_hasher: &mut Sha256,
562:                t: ty::t,
librustc/middle/trans/context.rs:
110:     pub adt_reprs: RefCell<HashMap<ty::t, Rc<adt::Repr>>>,
111:     pub symbol_hasher: RefCell<Sha256>,
112:     pub type_hashcodes: RefCell<HashMap<ty::t, ~str>>,