1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163
//! Ed25519 keys can be converted to X25519 keys, so that the same key pair can be used both for authenticated
//! encryption (crypto_box) and for signatures (crypto_sign).
#![no_std]
#![allow(clippy::all)]
mod field;
mod field_element_2625;
mod sha512;
use field::FieldElement;
/// Convert Ed25519 public key to Curve25519 public key.
///
/// # Example
///
/// ```rust
/// use ed25519_to_curve25519::*;
/// let ed25519_pk = [
/// 59, 106, 39, 188, 206, 182, 164, 45, 98, 163, 168, 208, 42, 111, 13, 115, 101, 50, 21, 119,
/// 29, 226, 67, 166, 58, 192, 72, 161, 139, 89, 218, 41,
/// ];
/// let curve25519_pk = [
/// 91, 245, 92, 115, 184, 46, 190, 34, 190, 128, 243, 67, 6, 103, 175, 87, 15, 174, 37, 86,
/// 166, 65, 94, 107, 48, 212, 6, 83, 0, 170, 148, 125,
/// ];
/// assert_eq!(ed25519_pk_to_curve25519(ed25519_pk), curve25519_pk)
/// ```
///
#[allow(non_snake_case)]
pub fn ed25519_pk_to_curve25519(pk: [u8; 32]) -> [u8; 32] {
let AY = FieldElement::from_bytes(&pk);
let mut one_minus_y = FieldElement::one();
one_minus_y = &one_minus_y - &AY;
one_minus_y = one_minus_y.invert();
let mut x = FieldElement::one();
x = &x + &AY;
x = &x * &one_minus_y;
x.to_bytes()
}
/// Convert Ed25519 secret key to Curve25519 secret key.
///
/// # Example
///
/// ```rust
/// use ed25519_to_curve25519::*;
/// let ed25519_sk = [
/// 202, 104, 239, 81, 53, 110, 80, 252, 198, 23, 155, 162, 215, 98, 223, 173, 227, 188, 110,
/// 54, 127, 45, 185, 206, 174, 29, 44, 147, 76, 66, 196, 195,
/// ];
/// let curve25519_sk = [
/// 200, 255, 64, 61, 17, 52, 112, 33, 205, 71, 186, 13, 131, 12, 241, 136, 223, 5, 152, 40,
/// 95, 187, 83, 168, 142, 10, 234, 215, 70, 210, 148, 104,
/// ];
/// assert_eq!(ed25519_sk_to_curve25519(ed25519_sk), curve25519_sk)
/// ```
///
pub fn ed25519_sk_to_curve25519(sk: [u8; 32]) -> [u8; 32] {
let mut h = sha512::sha512(&sk);
h[0] &= 248;
h[31] &= 127;
h[31] |= 64;
let mut result = [0u8; 32];
result.copy_from_slice(&h[..32]);
result
}
/// Convert Ed25519 sign to Curve25519 sign.
///
/// # Example
///
/// ```rust
/// use ed25519_to_curve25519::*;
/// let ed25519_pk = [
/// 59, 106, 39, 188, 206, 182, 164, 45, 98, 163, 168, 208, 42, 111, 13, 115, 101, 50, 21, 119,
/// 29, 226, 67, 166, 58, 192, 72, 161, 139, 89, 218, 41,
/// ];
/// let ed25519_sign = [202, 104, 239, 81, 53, 110, 80, 252, 198, 23, 155, 162, 215, 98, 223, 173, 227, 188, 110,
/// 54, 127, 45, 185, 206, 174, 29, 44, 147, 76, 66, 196, 195, 53, 164, 40, 138, 28, 75, 103,
/// 138, 219, 26, 134, 231, 237, 187, 70, 163, 58, 141, 120, 77, 248, 226, 86, 102, 171, 130,
/// 120, 95, 109, 87, 13, 12,
/// ];
/// let curve25519_sign = [
/// 202, 104, 239, 81, 53, 110, 80, 252, 198, 23, 155, 162, 215, 98, 223, 173, 227, 188, 110,
/// 54, 127, 45, 185, 206, 174, 29, 44, 147, 76, 66, 196, 195, 53, 164, 40, 138, 28, 75, 103,
/// 138, 219, 26, 134, 231, 237, 187, 70, 163, 58, 141, 120, 77, 248, 226, 86, 102, 171, 130,
/// 120, 95, 109, 87, 13, 12,
/// ];
/// assert_eq!(ed25519_sign_to_curve25519(ed25519_pk, ed25519_sign), curve25519_sign)
/// ```
///
pub fn ed25519_sign_to_curve25519(pk: [u8; 32], sign: [u8; 64]) -> [u8; 64] {
let mut result = sign;
let sign_bit = pk[31] & 0x80;
result[63] = result[63] | sign_bit;
result
}
#[cfg(test)]
mod tests {
use super::*;
const ED25519_PK: [u8; 32] = [
59, 106, 39, 188, 206, 182, 164, 45, 98, 163, 168, 208, 42, 111, 13, 115, 101, 50, 21, 119,
29, 226, 67, 166, 58, 192, 72, 161, 139, 89, 218, 41,
];
const CURVE25519_PK: [u8; 32] = [
91, 245, 92, 115, 184, 46, 190, 34, 190, 128, 243, 67, 6, 103, 175, 87, 15, 174, 37, 86,
166, 65, 94, 107, 48, 212, 6, 83, 0, 170, 148, 125,
];
const ED25519_SK: [u8; 32] = [
202, 104, 239, 81, 53, 110, 80, 252, 198, 23, 155, 162, 215, 98, 223, 173, 227, 188, 110,
54, 127, 45, 185, 206, 174, 29, 44, 147, 76, 66, 196, 195,
];
const CURVE25519_SK: [u8; 32] = [
200, 255, 64, 61, 17, 52, 112, 33, 205, 71, 186, 13, 131, 12, 241, 136, 223, 5, 152, 40,
95, 187, 83, 168, 142, 10, 234, 215, 70, 210, 148, 104,
];
const ED25519_SIGN: [u8; 64] = [
202, 104, 239, 81, 53, 110, 80, 252, 198, 23, 155, 162, 215, 98, 223, 173, 227, 188, 110,
54, 127, 45, 185, 206, 174, 29, 44, 147, 76, 66, 196, 195, 53, 164, 40, 138, 28, 75, 103,
138, 219, 26, 134, 231, 237, 187, 70, 163, 58, 141, 120, 77, 248, 226, 86, 102, 171, 130,
120, 95, 109, 87, 13, 12,
];
const CURVE25519_SIGN: [u8; 64] = [
202, 104, 239, 81, 53, 110, 80, 252, 198, 23, 155, 162, 215, 98, 223, 173, 227, 188, 110,
54, 127, 45, 185, 206, 174, 29, 44, 147, 76, 66, 196, 195, 53, 164, 40, 138, 28, 75, 103,
138, 219, 26, 134, 231, 237, 187, 70, 163, 58, 141, 120, 77, 248, 226, 86, 102, 171, 130,
120, 95, 109, 87, 13, 12,
];
#[test]
fn test_ed25519_pk_to_curve25519() {
assert_eq!(ed25519_pk_to_curve25519(ED25519_PK), CURVE25519_PK);
}
#[test]
fn test_ed25519_sk_to_curve25519() {
assert_eq!(ed25519_sk_to_curve25519(ED25519_SK), CURVE25519_SK);
}
#[test]
fn test_ed25519_sign_to_curve25519() {
assert_eq!(
ed25519_sign_to_curve25519(ED25519_PK, ED25519_SIGN),
CURVE25519_SIGN
);
}
}