use crate::{backend, hash::HashInto, marker::*, op};
use core::{
marker::PhantomData,
ops::{AddAssign, MulAssign, SubAssign},
};
use digest::{generic_array::typenum::U32, Digest};
use rand_core::RngCore;
pub struct Scalar<S = Secret, Z = NonZero>(pub(crate) backend::Scalar, PhantomData<(Z, S)>);
impl<Z> Copy for Scalar<Public, Z> {}
impl<S, Z> Clone for Scalar<S, Z> {
fn clone(&self) -> Self {
Self(self.0.clone(), self.1.clone())
}
}
impl<Z> core::hash::Hash for Scalar<Public, Z> {
fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
self.to_bytes().hash(state)
}
}
impl<Z, S> Scalar<S, Z> {
pub fn to_bytes(&self) -> [u8; 32] {
backend::BackendScalar::to_bytes(&self.0)
}
pub fn conditional_negate(&mut self, cond: bool) {
op::scalar_conditional_negate(self, cond)
}
pub fn is_high(&self) -> bool {
op::scalar_is_high(self)
}
pub fn is_zero(&self) -> bool {
op::scalar_is_zero(self)
}
pub(crate) fn from_inner(inner: backend::Scalar) -> Self {
Scalar(inner, PhantomData)
}
pub fn set_secrecy<SNew>(self) -> Scalar<SNew, Z> {
Scalar::from_inner(self.0)
}
pub fn public(self) -> Scalar<Public, Z> {
Scalar::from_inner(self.0)
}
pub fn secret(self) -> Scalar<Secret, Z> {
Scalar::from_inner(self.0)
}
pub fn mark_zero(self) -> Scalar<S, Zero> {
Scalar::from_inner(self.0)
}
}
impl<S> Scalar<S, NonZero> {
pub fn invert(&self) -> Self {
op::scalar_invert(self)
}
pub fn one() -> Self {
Scalar::from(1).non_zero().unwrap()
}
pub fn minus_one() -> Self {
Self::from_inner(backend::BackendScalar::minus_one())
}
}
impl Scalar<Secret, NonZero> {
pub fn random<R: RngCore>(rng: &mut R) -> Self {
let mut bytes = [0u8; 32];
rng.fill_bytes(&mut bytes);
Scalar::from_bytes_mod_order(bytes)
.non_zero()
.expect("computationally unreachable")
}
pub fn from_hash(hash: impl Digest<OutputSize = U32>) -> Self {
let mut bytes = [0u8; 32];
bytes.copy_from_slice(hash.finalize().as_slice());
Scalar::from_bytes_mod_order(bytes)
.non_zero()
.expect("computationally unreachable")
}
pub fn from_non_zero_u32(int: core::num::NonZeroU32) -> Self {
Self::from_inner(backend::BackendScalar::from_u32(int.get()))
}
}
impl<S> Scalar<S, Zero> {
pub fn non_zero(self) -> Option<Scalar<S, NonZero>> {
if self.is_zero() {
None
} else {
Some(Scalar::from_inner(self.0))
}
}
pub fn zero() -> Self {
Self::from_inner(backend::BackendScalar::zero())
}
pub fn from_bytes_mod_order(bytes: [u8; 32]) -> Self {
Self::from_inner(backend::BackendScalar::from_bytes_mod_order(bytes))
}
pub fn from_slice_mod_order(slice: &[u8]) -> Option<Self> {
if slice.len() != 32 {
return None;
}
let mut bytes = [0u8; 32];
bytes.copy_from_slice(slice);
Some(Self::from_bytes_mod_order(bytes))
}
pub fn from_bytes(bytes: [u8; 32]) -> Option<Self> {
backend::BackendScalar::from_bytes(bytes).map(Self::from_inner)
}
pub fn from_slice(slice: &[u8]) -> Option<Self> {
if slice.len() != 32 {
return None;
}
let mut bytes = [0u8; 32];
bytes.copy_from_slice(&slice);
Self::from_bytes(bytes)
}
}
impl<Z1, Z2, S1, S2> PartialEq<Scalar<S2, Z2>> for Scalar<S1, Z1> {
fn eq(&self, rhs: &Scalar<S2, Z2>) -> bool {
crate::op::scalar_eq(self, rhs)
}
}
impl<Z, S> Eq for Scalar<Z, S> {}
impl<S> From<u32> for Scalar<S, Zero> {
fn from(int: u32) -> Self {
Self::from_inner(backend::BackendScalar::from_u32(int))
}
}
crate::impl_fromstr_deserialize! {
name => "non-zero secp256k1 scalar",
fn from_bytes<S>(bytes: [u8;32]) -> Option<Scalar<S,NonZero>> {
Scalar::from_bytes(bytes).and_then(|scalar| scalar.set_secrecy::<S>().non_zero())
}
}
crate::impl_display_debug_serialize! {
fn to_bytes<Z,S>(scalar: &Scalar<S,Z>) -> [u8;32] {
scalar.to_bytes()
}
}
crate::impl_fromstr_deserialize! {
name => "secp256k1 scalar",
fn from_bytes<S>(bytes: [u8;32]) -> Option<Scalar<S,Zero>> {
Scalar::from_bytes(bytes).map(|scalar| scalar.set_secrecy::<S>())
}
}
impl<S, Z> core::ops::Neg for Scalar<S, Z> {
type Output = Scalar<S, Z>;
fn neg(self) -> Self::Output {
crate::op::scalar_negate(&self)
}
}
impl<S, Z> core::ops::Neg for &Scalar<S, Z> {
type Output = Scalar<S, Z>;
fn neg(self) -> Self::Output {
crate::op::scalar_negate(self)
}
}
impl<S, Z> HashInto for Scalar<S, Z> {
fn hash_into(self, hash: &mut impl digest::Digest) {
hash.update(&self.to_bytes())
}
}
impl<S> Default for Scalar<S, Zero>
where
S: Secrecy,
{
fn default() -> Self {
Scalar::<S, _>::zero()
}
}
impl<S> Default for Scalar<S, NonZero>
where
S: Secrecy,
{
fn default() -> Self {
Self::from_inner(backend::BackendScalar::from_u32(1))
}
}
impl<SL, SR, ZR> AddAssign<Scalar<SR, ZR>> for Scalar<SL, Zero> {
fn add_assign(&mut self, rhs: Scalar<SR, ZR>) {
*self = crate::op::scalar_add(&self, &rhs).set_secrecy::<SL>();
}
}
impl<SL, SR, ZR> AddAssign<&Scalar<SR, ZR>> for Scalar<SL, Zero> {
fn add_assign(&mut self, rhs: &Scalar<SR, ZR>) {
*self = crate::op::scalar_add(&self, rhs).set_secrecy::<SL>();
}
}
impl<SL, SR, ZR> SubAssign<&Scalar<SR, ZR>> for Scalar<SL, Zero> {
fn sub_assign(&mut self, rhs: &Scalar<SR, ZR>) {
*self = crate::op::scalar_sub(&self, rhs).set_secrecy::<SL>();
}
}
impl<SL, SR, ZR> SubAssign<Scalar<SR, ZR>> for Scalar<SL, Zero> {
fn sub_assign(&mut self, rhs: Scalar<SR, ZR>) {
*self = crate::op::scalar_sub(&self, &rhs).set_secrecy::<SL>();
}
}
impl<SL, SR> MulAssign<Scalar<SR, NonZero>> for Scalar<SL, NonZero> {
fn mul_assign(&mut self, rhs: Scalar<SR, NonZero>) {
*self = crate::op::scalar_mul(&self, &rhs).set_secrecy::<SL>();
}
}
impl<SL, SR> MulAssign<&Scalar<SR, NonZero>> for Scalar<SL, NonZero> {
fn mul_assign(&mut self, rhs: &Scalar<SR, NonZero>) {
*self = crate::op::scalar_mul(&self, rhs).set_secrecy::<SL>();
}
}
impl<SL, SR, ZR: ZeroChoice> MulAssign<Scalar<SR, ZR>> for Scalar<SL, Zero> {
fn mul_assign(&mut self, rhs: Scalar<SR, ZR>) {
*self = crate::op::scalar_mul(&self, &rhs).set_secrecy::<SL>();
}
}
impl<SL, SR, ZR: ZeroChoice> MulAssign<&Scalar<SR, ZR>> for Scalar<SL, Zero> {
fn mul_assign(&mut self, rhs: &Scalar<SR, ZR>) {
*self = crate::op::scalar_mul(&self, rhs).set_secrecy::<SL>();
}
}
impl<Z1, Z2> PartialOrd<Scalar<Public, Z2>> for Scalar<Public, Z1> {
fn partial_cmp(&self, other: &Scalar<Public, Z2>) -> Option<core::cmp::Ordering> {
Some(self.to_bytes().cmp(&other.to_bytes()))
}
}
impl<Z> Ord for Scalar<Public, Z> {
fn cmp(&self, other: &Self) -> core::cmp::Ordering {
self.to_bytes().cmp(&other.to_bytes())
}
}
#[cfg(test)]
mod test {
use super::*;
use crate::{hex, op, s};
use proptest::prelude::*;
#[cfg(target_arch = "wasm32")]
use wasm_bindgen_test::wasm_bindgen_test as test;
#[cfg(feature = "serde")]
#[test]
fn scalar_serde_rountrip() {
let original = Scalar::random(&mut rand::thread_rng());
let serialized = bincode::serialize(&original).unwrap();
let deserialized = bincode::deserialize::<Scalar>(&serialized[..]).unwrap();
assert_eq!(deserialized, original)
}
#[test]
fn random() {
let scalar_1 = Scalar::random(&mut rand::thread_rng());
let scalar_2 = Scalar::random(&mut rand::thread_rng());
assert_ne!(scalar_1, scalar_2);
}
proptest! {
#[test]
fn invert(x in any::<Scalar>(), y in any::<Scalar<Public>>()) {
assert_eq!(s!(x * { x.invert() }), s!(1));
assert_eq!(s!(y * { y.invert() }), s!(1));
}
#[test]
fn sub(a in any::<Scalar>(),
b in any::<Scalar<Public>>(),
c in any::<Scalar<Public,Zero>>(),
d in any::<Scalar<Secret,Zero>>(),
) {
assert_eq!(s!(a - a), s!(0));
assert_eq!(s!(b - b), s!(0));
assert_eq!(s!(c - c), s!(0));
assert_eq!(s!(d - d), s!(0));
assert_eq!(s!(a - a), s!(-a + a));
assert_eq!(s!(a - b), s!(-b + a));
assert_eq!(s!(a - c), s!(-c + a));
assert_eq!(s!(a - d), s!(-d + a));
if a != b {
assert_ne!(s!(a - b), s!(b - a));
}
if c != d {
assert_ne!(s!(c - d), s!(d - c));
}
}
}
#[test]
fn scalar_subtraction_is_not_commutative() {
let two = s!(2);
let three = s!(3);
let minus_1 = s!(-1);
let one = s!(1);
assert_eq!(s!(two - three), minus_1);
assert_eq!(s!(three - two), one);
}
#[test]
fn one() {
assert_eq!(
Scalar::<Secret, NonZero>::one(),
Scalar::<Secret, _>::from(1u32)
);
assert_eq!(
Scalar::<Secret, NonZero>::minus_one(),
-Scalar::<Secret, NonZero>::one()
);
assert_eq!(
op::scalar_mul(&s!(3), &Scalar::<Secret, NonZero>::minus_one()),
-s!(3)
);
}
#[test]
fn zero() {
assert_eq!(Scalar::<Secret, Zero>::zero(), Scalar::<Secret, _>::from(0));
}
#[test]
fn from_slice() {
assert!(
Scalar::<Secret, _>::from_slice(b"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx".as_ref()).is_some()
);
assert!(
Scalar::<Secret, _>::from_slice(b"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx".as_ref())
.is_none()
);
assert!(Scalar::<Secret, _>::from_slice(
hex::decode_array::<32>(
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
)
.unwrap()
.as_ref()
)
.is_none());
}
#[test]
fn from_slice_mod_order() {
assert_eq!(
Scalar::<Secret, _>::from_slice_mod_order(b"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx".as_ref())
.unwrap()
.to_bytes(),
*b"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
);
assert_eq!(
Scalar::<Secret, _>::from_slice_mod_order(
hex::decode_array::<32>(
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364142"
)
.unwrap()
.as_ref()
)
.unwrap(),
Scalar::<Secret, _>::from(1)
)
}
#[test]
fn minus_one() {
assert_eq!(
Scalar::<Secret, _>::minus_one(),
Scalar::<Secret, _>::from_bytes_mod_order(
hex::decode_array(
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364140"
)
.unwrap()
)
);
}
#[test]
fn assign_tests() {
let mut a = Scalar::<Secret, _>::from(42);
let b = Scalar::<Secret, _>::from(1337).public();
a += b;
assert_eq!(a, Scalar::<Secret, _>::from(1379));
a -= b;
assert_eq!(a, Scalar::<Secret, _>::from(42));
a *= b;
assert_eq!(a, Scalar::<Secret, _>::from(42 * 1337));
}
}