1//! The SHA family of hashes. 2//! 3//! SHA, or Secure Hash Algorithms, are a family of cryptographic hashing algorithms published by 4//! the National Institute of Standards and Technology (NIST). Hash algorithms such as those in 5//! the SHA family are used to map data of an arbitrary size to a fixed-size string of bytes. 6//! As cryptographic hashing algorithms, these mappings have the property of being irreversible. 7//! This property makes hash algorithms like these excellent for uses such as verifying the 8//! contents of a file- if you know the hash you expect beforehand, then you can verify that the 9//! data you have is correct if it hashes to the same value. 10//! 11//! # Examples 12//! 13//! When dealing with data that becomes available in chunks, such as while buffering data from IO, 14//! you can create a hasher that you can repeatedly update to add bytes to. 15//! 16//! ```rust 17//! use openssl::sha; 18//! 19//! let mut hasher = sha::Sha256::new(); 20//! 21//! hasher.update(b"Hello, "); 22//! hasher.update(b"world"); 23//! 24//! let hash = hasher.finish(); 25//! println!("Hashed \"Hello, world\" to {}", hex::encode(hash)); 26//! ``` 27//! 28//! On the other hand, if you already have access to all of the data you would like to hash, you 29//! may prefer to use the slightly simpler method of simply calling the hash function corresponding 30//! to the algorithm you want to use. 31//! 32//! ```rust 33//! use openssl::sha::sha256; 34//! 35//! let hash = sha256(b"your data or message"); 36//! println!("Hash = {}", hex::encode(hash)); 37//! ``` 38use cfg_if::cfg_if; 39use libc::c_void; 40use openssl_macros::corresponds; 41use std::mem::MaybeUninit; 42 43/// Computes the SHA1 hash of some data. 44/// 45/// # Warning 46/// 47/// SHA1 is known to be insecure - it should not be used unless required for 48/// compatibility with existing systems. 49#[corresponds(SHA1)] 50#[inline] 51pub fn sha1(data: &[u8]) -> [u8; 20] { 52 unsafe { 53 let mut hash = MaybeUninit::<[u8; 20]>::uninit(); 54 ffi::SHA1(data.as_ptr(), data.len(), hash.as_mut_ptr() as *mut _); 55 hash.assume_init() 56 } 57} 58 59/// Computes the SHA224 hash of some data. 60#[corresponds(SHA224)] 61#[inline] 62pub fn sha224(data: &[u8]) -> [u8; 28] { 63 unsafe { 64 let mut hash = MaybeUninit::<[u8; 28]>::uninit(); 65 ffi::SHA224(data.as_ptr(), data.len(), hash.as_mut_ptr() as *mut _); 66 hash.assume_init() 67 } 68} 69 70/// Computes the SHA256 hash of some data. 71#[corresponds(SHA256)] 72#[inline] 73pub fn sha256(data: &[u8]) -> [u8; 32] { 74 unsafe { 75 let mut hash = MaybeUninit::<[u8; 32]>::uninit(); 76 ffi::SHA256(data.as_ptr(), data.len(), hash.as_mut_ptr() as *mut _); 77 hash.assume_init() 78 } 79} 80 81/// Computes the SHA384 hash of some data. 82#[corresponds(SHA384)] 83#[inline] 84pub fn sha384(data: &[u8]) -> [u8; 48] { 85 unsafe { 86 let mut hash = MaybeUninit::<[u8; 48]>::uninit(); 87 ffi::SHA384(data.as_ptr(), data.len(), hash.as_mut_ptr() as *mut _); 88 hash.assume_init() 89 } 90} 91 92/// Computes the SHA512 hash of some data. 93#[corresponds(SHA512)] 94#[inline] 95pub fn sha512(data: &[u8]) -> [u8; 64] { 96 unsafe { 97 let mut hash = MaybeUninit::<[u8; 64]>::uninit(); 98 ffi::SHA512(data.as_ptr(), data.len(), hash.as_mut_ptr() as *mut _); 99 hash.assume_init() 100 } 101} 102 103cfg_if! { 104 if #[cfg(not(osslconf = "OPENSSL_NO_DEPRECATED_3_0"))] { 105 /// An object which calculates a SHA1 hash of some data. 106 /// 107 /// # Warning 108 /// 109 /// SHA1 is known to be insecure - it should not be used unless required for 110 /// compatibility with existing systems. 111 #[derive(Clone)] 112 pub struct Sha1(ffi::SHA_CTX); 113 114 impl Default for Sha1 { 115 #[inline] 116 fn default() -> Sha1 { 117 Sha1::new() 118 } 119 } 120 121 impl Sha1 { 122 /// Creates a new hasher. 123 #[corresponds(SHA1_Init)] 124 #[inline] 125 pub fn new() -> Sha1 { 126 unsafe { 127 let mut ctx = MaybeUninit::uninit(); 128 ffi::SHA1_Init( ctx.as_mut_ptr()); 129 Sha1(ctx.assume_init()) 130 } 131 } 132 133 /// Feeds some data into the hasher. 134 /// 135 /// This can be called multiple times. 136 #[corresponds(SHA1_Update)] 137 #[inline] 138 pub fn update(&mut self, buf: &[u8]) { 139 unsafe { 140 ffi::SHA1_Update(&mut self.0, buf.as_ptr() as *const c_void, buf.len()); 141 } 142 } 143 144 /// Returns the hash of the data. 145 #[corresponds(SHA1_Final)] 146 #[inline] 147 pub fn finish(mut self) -> [u8; 20] { 148 unsafe { 149 let mut hash = MaybeUninit::<[u8; 20]>::uninit(); 150 ffi::SHA1_Final(hash.as_mut_ptr() as *mut _, &mut self.0); 151 hash.assume_init() 152 } 153 } 154 } 155 156 /// An object which calculates a SHA224 hash of some data. 157 #[derive(Clone)] 158 pub struct Sha224(ffi::SHA256_CTX); 159 160 impl Default for Sha224 { 161 #[inline] 162 fn default() -> Sha224 { 163 Sha224::new() 164 } 165 } 166 167 impl Sha224 { 168 /// Creates a new hasher. 169 #[corresponds(SHA224_Init)] 170 #[inline] 171 pub fn new() -> Sha224 { 172 unsafe { 173 let mut ctx = MaybeUninit::uninit(); 174 ffi::SHA224_Init(ctx.as_mut_ptr()); 175 Sha224(ctx.assume_init()) 176 } 177 } 178 179 /// Feeds some data into the hasher. 180 /// 181 /// This can be called multiple times. 182 #[corresponds(SHA224_Update)] 183 #[inline] 184 pub fn update(&mut self, buf: &[u8]) { 185 unsafe { 186 ffi::SHA224_Update(&mut self.0, buf.as_ptr() as *const c_void, buf.len()); 187 } 188 } 189 190 /// Returns the hash of the data. 191 #[corresponds(SHA224_Final)] 192 #[inline] 193 pub fn finish(mut self) -> [u8; 28] { 194 unsafe { 195 let mut hash = MaybeUninit::<[u8; 28]>::uninit(); 196 ffi::SHA224_Final(hash.as_mut_ptr() as *mut _, &mut self.0); 197 hash.assume_init() 198 } 199 } 200 } 201 202 /// An object which calculates a SHA256 hash of some data. 203 #[derive(Clone)] 204 pub struct Sha256(ffi::SHA256_CTX); 205 206 impl Default for Sha256 { 207 #[inline] 208 fn default() -> Sha256 { 209 Sha256::new() 210 } 211 } 212 213 impl Sha256 { 214 /// Creates a new hasher. 215 #[corresponds(SHA256_Init)] 216 #[inline] 217 pub fn new() -> Sha256 { 218 unsafe { 219 let mut ctx = MaybeUninit::uninit(); 220 ffi::SHA256_Init(ctx.as_mut_ptr()); 221 Sha256(ctx.assume_init()) 222 } 223 } 224 225 /// Feeds some data into the hasher. 226 /// 227 /// This can be called multiple times. 228 #[corresponds(SHA256_Update)] 229 #[inline] 230 pub fn update(&mut self, buf: &[u8]) { 231 unsafe { 232 ffi::SHA256_Update(&mut self.0, buf.as_ptr() as *const c_void, buf.len()); 233 } 234 } 235 236 /// Returns the hash of the data. 237 #[corresponds(SHA256_Final)] 238 #[inline] 239 pub fn finish(mut self) -> [u8; 32] { 240 unsafe { 241 let mut hash = MaybeUninit::<[u8; 32]>::uninit(); 242 ffi::SHA256_Final(hash.as_mut_ptr() as *mut _, &mut self.0); 243 hash.assume_init() 244 } 245 } 246 } 247 248 /// An object which calculates a SHA384 hash of some data. 249 #[derive(Clone)] 250 pub struct Sha384(ffi::SHA512_CTX); 251 252 impl Default for Sha384 { 253 #[inline] 254 fn default() -> Sha384 { 255 Sha384::new() 256 } 257 } 258 259 impl Sha384 { 260 /// Creates a new hasher. 261 #[corresponds(SHA384_Init)] 262 #[inline] 263 pub fn new() -> Sha384 { 264 unsafe { 265 let mut ctx = MaybeUninit::uninit(); 266 ffi::SHA384_Init(ctx.as_mut_ptr()); 267 Sha384(ctx.assume_init()) 268 } 269 } 270 271 /// Feeds some data into the hasher. 272 /// 273 /// This can be called multiple times. 274 #[corresponds(SHA384_Update)] 275 #[inline] 276 pub fn update(&mut self, buf: &[u8]) { 277 unsafe { 278 ffi::SHA384_Update(&mut self.0, buf.as_ptr() as *const c_void, buf.len()); 279 } 280 } 281 282 /// Returns the hash of the data. 283 #[corresponds(SHA384_Final)] 284 #[inline] 285 pub fn finish(mut self) -> [u8; 48] { 286 unsafe { 287 let mut hash = MaybeUninit::<[u8; 48]>::uninit(); 288 ffi::SHA384_Final(hash.as_mut_ptr() as *mut _, &mut self.0); 289 hash.assume_init() 290 } 291 } 292 } 293 294 /// An object which calculates a SHA512 hash of some data. 295 #[derive(Clone)] 296 pub struct Sha512(ffi::SHA512_CTX); 297 298 impl Default for Sha512 { 299 #[inline] 300 fn default() -> Sha512 { 301 Sha512::new() 302 } 303 } 304 305 impl Sha512 { 306 /// Creates a new hasher. 307 #[corresponds(SHA512_Init)] 308 #[inline] 309 pub fn new() -> Sha512 { 310 unsafe { 311 let mut ctx = MaybeUninit::uninit(); 312 ffi::SHA512_Init(ctx.as_mut_ptr()); 313 Sha512(ctx.assume_init()) 314 } 315 } 316 317 /// Feeds some data into the hasher. 318 /// 319 /// This can be called multiple times. 320 #[corresponds(SHA512_Update)] 321 #[inline] 322 pub fn update(&mut self, buf: &[u8]) { 323 unsafe { 324 ffi::SHA512_Update(&mut self.0, buf.as_ptr() as *const c_void, buf.len()); 325 } 326 } 327 328 /// Returns the hash of the data. 329 #[corresponds(SHA512_Final)] 330 #[inline] 331 pub fn finish(mut self) -> [u8; 64] { 332 unsafe { 333 let mut hash= MaybeUninit::<[u8; 64]>::uninit(); 334 ffi::SHA512_Final(hash.as_mut_ptr() as *mut _, &mut self.0); 335 hash.assume_init() 336 } 337 } 338 } 339 } 340} 341 342#[cfg(test)] 343mod test { 344 use super::*; 345 346 #[test] 347 fn standalone_1() { 348 let data = b"abc"; 349 let expected = "a9993e364706816aba3e25717850c26c9cd0d89d"; 350 351 assert_eq!(hex::encode(sha1(data)), expected); 352 } 353 354 #[test] 355 #[cfg(not(osslconf = "OPENSSL_NO_DEPRECATED_3_0"))] 356 fn struct_1() { 357 let expected = "a9993e364706816aba3e25717850c26c9cd0d89d"; 358 359 let mut hasher = Sha1::new(); 360 hasher.update(b"a"); 361 hasher.update(b"bc"); 362 assert_eq!(hex::encode(hasher.finish()), expected); 363 } 364 365 #[test] 366 #[cfg(not(osslconf = "OPENSSL_NO_DEPRECATED_3_0"))] 367 fn cloning_allows_incremental_hashing() { 368 let expected = "a9993e364706816aba3e25717850c26c9cd0d89d"; 369 370 let mut hasher = Sha1::new(); 371 hasher.update(b"a"); 372 373 let mut incr_hasher = hasher.clone(); 374 incr_hasher.update(b"bc"); 375 376 assert_eq!(hex::encode(incr_hasher.finish()), expected); 377 assert_ne!(hex::encode(hasher.finish()), expected); 378 } 379 380 #[test] 381 fn standalone_224() { 382 let data = b"abc"; 383 let expected = "23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7"; 384 385 assert_eq!(hex::encode(sha224(data)), expected); 386 } 387 388 #[test] 389 #[cfg(not(osslconf = "OPENSSL_NO_DEPRECATED_3_0"))] 390 fn struct_224() { 391 let expected = "23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7"; 392 393 let mut hasher = Sha224::new(); 394 hasher.update(b"a"); 395 hasher.update(b"bc"); 396 assert_eq!(hex::encode(hasher.finish()), expected); 397 } 398 399 #[test] 400 fn standalone_256() { 401 let data = b"abc"; 402 let expected = "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"; 403 404 assert_eq!(hex::encode(sha256(data)), expected); 405 } 406 407 #[test] 408 #[cfg(not(osslconf = "OPENSSL_NO_DEPRECATED_3_0"))] 409 fn struct_256() { 410 let expected = "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"; 411 412 let mut hasher = Sha256::new(); 413 hasher.update(b"a"); 414 hasher.update(b"bc"); 415 assert_eq!(hex::encode(hasher.finish()), expected); 416 } 417 418 #[test] 419 fn standalone_384() { 420 let data = b"abc"; 421 let expected = 422 "cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e\ 423 7cc2358baeca134c825a7"; 424 425 assert_eq!(hex::encode(&sha384(data)[..]), expected); 426 } 427 428 #[test] 429 #[cfg(not(osslconf = "OPENSSL_NO_DEPRECATED_3_0"))] 430 fn struct_384() { 431 let expected = 432 "cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e\ 433 7cc2358baeca134c825a7"; 434 435 let mut hasher = Sha384::new(); 436 hasher.update(b"a"); 437 hasher.update(b"bc"); 438 assert_eq!(hex::encode(&hasher.finish()[..]), expected); 439 } 440 441 #[test] 442 fn standalone_512() { 443 let data = b"abc"; 444 let expected = 445 "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274\ 446 fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f"; 447 448 assert_eq!(hex::encode(&sha512(data)[..]), expected); 449 } 450 451 #[test] 452 #[cfg(not(osslconf = "OPENSSL_NO_DEPRECATED_3_0"))] 453 fn struct_512() { 454 let expected = 455 "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274\ 456 fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f"; 457 458 let mut hasher = Sha512::new(); 459 hasher.update(b"a"); 460 hasher.update(b"bc"); 461 assert_eq!(hex::encode(&hasher.finish()[..]), expected); 462 } 463} 464