Create a Digest trait for common methods on digests and convert the SHA-1 implementation to use it.
The DigestUtil trait was created for helper methods since default methods still have issues.
This commit is contained in:
parent
e1b8c67580
commit
89eef0b139
4 changed files with 119 additions and 37 deletions
88
src/libextra/crypto/digest.rs
Normal file
88
src/libextra/crypto/digest.rs
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use core::prelude::*;
|
||||
|
||||
use core::uint;
|
||||
use core::vec;
|
||||
|
||||
/**
|
||||
* The Digest trait specifies an interface common to digest functions, such as SHA-1 and the SHA-2
|
||||
* family of digest functions.
|
||||
*/
|
||||
pub trait Digest {
|
||||
/**
|
||||
* Provide message data.
|
||||
*
|
||||
* # Arguments
|
||||
*
|
||||
* * input - A vector of message data
|
||||
*/
|
||||
fn input(&mut self, input: &[u8]);
|
||||
|
||||
/**
|
||||
* Retrieve the digest result. This method may be called multiple times.
|
||||
*/
|
||||
fn result(&mut self, out: &mut [u8]);
|
||||
|
||||
/**
|
||||
* Reset the digest. This method must be called after result() and before supplying more
|
||||
* data.
|
||||
*/
|
||||
fn reset(&mut self);
|
||||
|
||||
/**
|
||||
* Get the output size in bits.
|
||||
*/
|
||||
fn output_bits(&self) -> uint;
|
||||
}
|
||||
|
||||
fn to_hex(rr: &[u8]) -> ~str {
|
||||
let mut s = ~"";
|
||||
for rr.iter().advance() |b| {
|
||||
let hex = uint::to_str_radix(*b as uint, 16u);
|
||||
if hex.len() == 1 {
|
||||
s += "0";
|
||||
}
|
||||
s += hex;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
/// Contains utility methods for Digests.
|
||||
/// FIXME: #7339: Convert to default methods when issues with them are resolved.
|
||||
pub trait DigestUtil {
|
||||
/**
|
||||
* Convenience functon that feeds a string into a digest
|
||||
*
|
||||
* # Arguments
|
||||
*
|
||||
* * in The string to feed into the digest
|
||||
*/
|
||||
fn input_str(&mut self, in: &str);
|
||||
|
||||
/**
|
||||
* Convenience functon that retrieves the result of a digest as a
|
||||
* ~str in hexadecimal format.
|
||||
*/
|
||||
fn result_str(&mut self) -> ~str;
|
||||
}
|
||||
|
||||
impl<D: Digest> DigestUtil for D {
|
||||
fn input_str(&mut self, in: &str) {
|
||||
self.input(in.as_bytes());
|
||||
}
|
||||
|
||||
fn result_str(&mut self) -> ~str {
|
||||
let mut buf = vec::from_elem((self.output_bits()+7)/8, 0u8);
|
||||
self.result(buf);
|
||||
return to_hex(buf);
|
||||
}
|
||||
}
|
||||
|
|
@ -24,7 +24,7 @@
|
|||
|
||||
use core::prelude::*;
|
||||
|
||||
use core::uint;
|
||||
use digest::Digest;
|
||||
|
||||
/*
|
||||
* A SHA-1 implementation derived from Paul E. Jones's reference
|
||||
|
|
@ -148,18 +148,17 @@ fn circular_shift(bits: u32, word: u32) -> u32 {
|
|||
return word << bits | word >> 32u32 - bits;
|
||||
}
|
||||
|
||||
fn mk_result(st: &mut Sha1) -> ~[u8] {
|
||||
fn mk_result(st: &mut Sha1, rs: &mut [u8]) {
|
||||
if !st.computed { pad_msg(st); st.computed = true; }
|
||||
let mut rs: ~[u8] = ~[];
|
||||
let mut i = 0;
|
||||
for st.h.mut_iter().advance |ptr_hpart| {
|
||||
let hpart = *ptr_hpart;
|
||||
let a = (hpart >> 24u32 & 0xFFu32) as u8;
|
||||
let b = (hpart >> 16u32 & 0xFFu32) as u8;
|
||||
let c = (hpart >> 8u32 & 0xFFu32) as u8;
|
||||
let d = (hpart & 0xFFu32) as u8;
|
||||
rs = vec::append(copy rs, [a, b, c, d]);
|
||||
rs[i] = (hpart >> 24u32 & 0xFFu32) as u8;
|
||||
rs[i+1] = (hpart >> 16u32 & 0xFFu32) as u8;
|
||||
rs[i+2] = (hpart >> 8u32 & 0xFFu32) as u8;
|
||||
rs[i+3] = (hpart & 0xFFu32) as u8;
|
||||
i += 4;
|
||||
}
|
||||
return rs;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -221,6 +220,9 @@ impl Sha1 {
|
|||
st.reset();
|
||||
return st;
|
||||
}
|
||||
}
|
||||
|
||||
impl Digest for Sha1 {
|
||||
pub fn reset(&mut self) {
|
||||
self.len_low = 0;
|
||||
self.len_high = 0;
|
||||
|
|
@ -233,28 +235,15 @@ impl Sha1 {
|
|||
self.computed = false;
|
||||
}
|
||||
pub fn input(&mut self, msg: &[u8]) { add_input(self, msg); }
|
||||
pub fn input_str(&mut self, msg: &str) {
|
||||
add_input(self, msg.as_bytes());
|
||||
}
|
||||
pub fn result(&mut self) -> ~[u8] { return mk_result(self); }
|
||||
pub fn result_str(&mut self) -> ~str {
|
||||
let rr = mk_result(self);
|
||||
let mut s = ~"";
|
||||
for rr.iter().advance() |b| {
|
||||
let hex = uint::to_str_radix(*b as uint, 16u);
|
||||
if hex.len() == 1 {
|
||||
s += "0";
|
||||
}
|
||||
s += hex;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
pub fn result(&mut self, out: &mut [u8]) { return mk_result(self, out); }
|
||||
pub fn output_bits(&self) -> uint { 160 }
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use core::vec;
|
||||
|
||||
use digest::{Digest, DigestUtil};
|
||||
use sha1::Sha1;
|
||||
|
||||
#[test]
|
||||
|
|
@ -343,13 +332,15 @@ mod tests {
|
|||
|
||||
// Test that it works when accepting the message all at once
|
||||
|
||||
let mut out = [0u8, ..20];
|
||||
|
||||
let mut sh = ~Sha1::new();
|
||||
for tests.iter().advance |t| {
|
||||
sh.input_str(t.input);
|
||||
let out = sh.result();
|
||||
(*sh).input_str(t.input);
|
||||
sh.result(out);
|
||||
assert!(vec::eq(t.output, out));
|
||||
|
||||
let out_str = sh.result_str();
|
||||
let out_str = (*sh).result_str();
|
||||
assert_eq!(out_str.len(), 40);
|
||||
assert!(out_str == t.output_str);
|
||||
|
||||
|
|
@ -363,13 +354,13 @@ mod tests {
|
|||
let mut left = len;
|
||||
while left > 0u {
|
||||
let take = (left + 1u) / 2u;
|
||||
sh.input_str(t.input.slice(len - left, take + len - left));
|
||||
(*sh).input_str(t.input.slice(len - left, take + len - left));
|
||||
left = left - take;
|
||||
}
|
||||
let out = sh.result();
|
||||
sh.result(out);
|
||||
assert!(vec::eq(t.output, out));
|
||||
|
||||
let out_str = sh.result_str();
|
||||
let out_str = (*sh).result_str();
|
||||
assert_eq!(out_str.len(), 40);
|
||||
assert!(out_str == t.output_str);
|
||||
|
||||
|
|
|
|||
|
|
@ -87,6 +87,8 @@ pub mod dlist;
|
|||
pub mod treemap;
|
||||
|
||||
// Crypto
|
||||
#[path="crypto/digest.rs"]
|
||||
pub mod digest;
|
||||
#[path="crypto/sha1.rs"]
|
||||
pub mod sha1;
|
||||
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
|
||||
use core::prelude::*;
|
||||
|
||||
use digest::DigestUtil;
|
||||
use json;
|
||||
use sha1::Sha1;
|
||||
use serialize::{Encoder, Encodable, Decoder, Decodable};
|
||||
|
|
@ -248,16 +249,16 @@ fn json_decode<T:Decodable<json::Decoder>>(s: &str) -> T {
|
|||
}
|
||||
|
||||
fn digest<T:Encodable<json::Encoder>>(t: &T) -> ~str {
|
||||
let mut sha = Sha1::new();
|
||||
sha.input_str(json_encode(t));
|
||||
sha.result_str()
|
||||
let mut sha = ~Sha1::new();
|
||||
(*sha).input_str(json_encode(t));
|
||||
(*sha).result_str()
|
||||
}
|
||||
|
||||
fn digest_file(path: &Path) -> ~str {
|
||||
let mut sha = Sha1::new();
|
||||
let mut sha = ~Sha1::new();
|
||||
let s = io::read_whole_file_str(path);
|
||||
sha.input_str(*s.get_ref());
|
||||
sha.result_str()
|
||||
(*sha).input_str(*s.get_ref());
|
||||
(*sha).result_str()
|
||||
}
|
||||
|
||||
impl Context {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue