# Migration: `blake2` (RustCrypto) → `rscrypto`
> Same algorithms (RFC 7693), with named convenience types replacing `Blake2b<U32>`-style generic instantiations and `Blake2b256::keyed_digest(key, data)` replacing the separate `Blake2bMac<U32>` MAC type.
Verified against `blake2 = "0.11.0-rc.6"` and the `rscrypto` 0.7.8 line.
Evidence: `tests/blake2_official_vectors.rs` and `tests/blake2_differential.rs`.
Code samples use the 0.10-style names where they remain the clearest migration
shape for existing projects.
## TL;DR
| Cargo dep | `blake2 = "0.10"` | `rscrypto = { version = "0.7.8", features = ["blake2b", "blake2s"] }` |
| Import | `use blake2::{Blake2b512, Digest};` | `use rscrypto::{Blake2b512, Digest};` |
| Call | `Blake2b512::digest(data)` | `Blake2b512::digest(data)` |
Drop one or both of `blake2b` / `blake2s` from the feature list if you don't use that family.
## Cargo.toml
```toml
# Before
[dependencies]
blake2 = "0.10"
```
```toml
# After
[dependencies]
rscrypto = { version = "0.7.8", features = ["blake2b", "blake2s"] }
```
## Algorithm map
| `Blake2b<U32>` (generic) | `Blake2b256` | `[u8; 32]` |
| `Blake2b<U64>` or `Blake2b512` | `Blake2b512` | `[u8; 64]` |
| `Blake2b<UN>` (variable, runtime) | `Blake2b` | 1-64 bytes via `digest_into` |
| `Blake2s<U16>` | `Blake2s128` | `[u8; 16]` |
| `Blake2s<U32>` or `Blake2s256` | `Blake2s256` | `[u8; 32]` |
| `Blake2bMac<U32>` (keyed) | `Blake2b256::keyed_digest(...)` | `[u8; 32]` |
| `Blake2bMac512` (keyed, 512-bit) | `Blake2b512::keyed_digest(...)` | `[u8; 64]` |
| `Blake2sMac<U32>` (keyed) | `Blake2s256::keyed_digest(...)` | `[u8; 32]` |
`Blake2bp` / `Blake2sp` (parallel variants) are not currently mapped.
## API patterns
### Fixed-output one-shot
```rust
// Before
use blake2::{Blake2b512, Digest};
let out = Blake2b512::digest(b"123456789"); // Output<Blake2b512>
```
```rust
// After
use rscrypto::{Blake2b512, Digest};
let out: [u8; 64] = Blake2b512::digest(b"123456789");
```
### Custom-length Blake2b
```rust
// Before
use blake2::{Blake2b, Digest};
use blake2::digest::consts::U32;
let out = <Blake2b<U32> as Digest>::digest(b"123456789"); // [u8; 32] in an Output wrapper
```
```rust
// After
use rscrypto::{Blake2b256, Digest};
let out: [u8; 32] = Blake2b256::digest(b"123456789");
```
For runtime-variable output, size the destination and call
`Blake2b::digest_into(data, &mut buf)?`. The buffer length selects the output
length and invalid empty or oversized buffers return `Blake2Error`.
### Streaming
```rust
// Before
use blake2::{Blake2b512, Digest};
let mut hasher = Blake2b512::new();
hasher.update(b"foo");
hasher.update(b"bar");
let out = hasher.finalize(); // consumes hasher
```
```rust
// After
use rscrypto::{Blake2b512, Digest};
let mut hasher = Blake2b512::new();
hasher.update(b"foo");
hasher.update(b"bar");
let out = hasher.finalize(); // borrows &self
```
### Keyed mode (MAC)
```rust
// Before
use blake2::Blake2bMac512;
use blake2::digest::{KeyInit, Mac};
let key = [0x42u8; 32];
let mut mac = Blake2bMac512::new_from_slice(&key).unwrap();
mac.update(b"message");
let tag = mac.finalize().into_bytes(); // GenericArray<u8, U64>
```
```rust
// After
use rscrypto::{Blake2b512, Blake2bKey};
let key = [0x42u8; 32];
let key = Blake2bKey::new(&key)?;
let tag: [u8; 64] = Blake2b512::keyed_digest(key, b"message");
```
For streaming keyed mode, use `Blake2b512::new_keyed(key)`. `Blake2bKey::new`
rejects empty or oversized keys at the caller boundary; the borrowed validated
key can then be reused without allocation or copying. Omitting the keyed
constructor selects unkeyed hashing. The MAC type and the hash type are
unified: no separate `Blake2bMac` import.
## Notes
- **Generic constants gone.** `Blake2b<U32>` and `Blake2s<U16>` style generics are replaced with named convenience types per output length. `generic-array` is no longer in your dependency tree if rscrypto is your only consumer.
- **MAC unification.** RustCrypto separates `Blake2bMac` from `Blake2b`
because the MAC and the hash use different parameter blocks. rscrypto
exposes both modes from the same type via `keyed_digest` / `new_keyed`.
Personalization and salt are available through `Blake2bParams` /
`Blake2sParams`; tree hashing is not exposed.
- **Exact parameter fields.** `Blake2bParams` accepts `[u8; 16]` salt and
personalization fields; `Blake2sParams` accepts `[u8; 8]`. Pad deliberately
before the call when a protocol defines a shorter value.
- **`finalize` consumes vs. borrows.** Same as `sha2` / `sha3`: drop `.clone()`.
- **`Output<D>` → `[u8; N]`.** Same as `sha2` / `sha3`.
- **No generic keyed-output comparison.** rscrypto's Blake2 keyed digest
returns raw bytes without a generic secret-comparison API. Use HMAC, KMAC,
or typed `Blake3KeyedHash` verification when the protocol needs built-in
verification.
- **`no_std`.** Both crates support `no_std`. rscrypto runtime-detects SIMD when `std` is enabled and falls back to compile-time `target_feature` selection in `no_std` builds.