1 //! BigNum implementation
3 //! Large numbers are important for a cryptographic library. OpenSSL implementation
4 //! of BigNum uses dynamically assigned memory to store an array of bit chunks. This
5 //! allows numbers of any size to be compared and mathematical functions performed.
7 //! OpenSSL wiki describes the [`BIGNUM`] data structure.
12 //! use openssl::bn::BigNum;
13 //! use openssl::error::ErrorStack;
15 //! fn main() -> Result<(), ErrorStack> {
16 //! let a = BigNum::new()?; // a = 0
17 //! let b = BigNum::from_dec_str("1234567890123456789012345")?;
24 //! [`BIGNUM`]: https://wiki.openssl.org/index.php/Manual:Bn_internal(3)
26 use foreign_types
::{ForeignType, ForeignTypeRef}
;
28 use std
::cmp
::Ordering
;
29 use std
::ffi
::CString
;
30 use std
::ops
::{Add, Deref, Div, Mul, Neg, Rem, Shl, Shr, Sub}
;
33 use asn1
::Asn1Integer
;
34 use error
::ErrorStack
;
35 use string
::OpensslString
;
36 use {cvt, cvt_n, cvt_p}
;
41 BN_get_rfc2409_prime_1024
, BN_get_rfc2409_prime_768
, BN_get_rfc3526_prime_1536
,
42 BN_get_rfc3526_prime_2048
, BN_get_rfc3526_prime_3072
, BN_get_rfc3526_prime_4096
,
43 BN_get_rfc3526_prime_6144
, BN_get_rfc3526_prime_8192
, BN_is_negative
,
47 get_rfc2409_prime_1024
as BN_get_rfc2409_prime_1024
,
48 get_rfc2409_prime_768
as BN_get_rfc2409_prime_768
,
49 get_rfc3526_prime_1536
as BN_get_rfc3526_prime_1536
,
50 get_rfc3526_prime_2048
as BN_get_rfc3526_prime_2048
,
51 get_rfc3526_prime_3072
as BN_get_rfc3526_prime_3072
,
52 get_rfc3526_prime_4096
as BN_get_rfc3526_prime_4096
,
53 get_rfc3526_prime_6144
as BN_get_rfc3526_prime_6144
,
54 get_rfc3526_prime_8192
as BN_get_rfc3526_prime_8192
,
58 unsafe fn BN_is_negative(bn
: *const ffi
::BIGNUM
) -> c_int
{
64 /// Options for the most significant bits of a randomly generated `BigNum`.
65 pub struct MsbOption(c_int
);
68 /// The most significant bit of the number may be 0.
69 pub const MAYBE_ZERO
: MsbOption
= MsbOption(-1);
71 /// The most significant bit of the number must be 1.
72 pub const ONE
: MsbOption
= MsbOption(0);
74 /// The most significant two bits of the number must be 1.
76 /// The number of bits in the product of two such numbers will always be exactly twice the
77 /// number of bits in the original numbers.
78 pub const TWO_ONES
: MsbOption
= MsbOption(1);
81 foreign_type_and_impl_send_sync
! {
82 type CType
= ffi
::BN_CTX
;
83 fn drop
= ffi
::BN_CTX_free
;
85 /// Temporary storage for BigNums on the secure heap
87 /// BigNum values are stored dynamically and therefore can be expensive
88 /// to allocate. BigNumContext and the OpenSSL [`BN_CTX`] structure are used
89 /// internally when passing BigNum values between subroutines.
91 /// [`BN_CTX`]: https://www.openssl.org/docs/man1.1.0/crypto/BN_CTX_new.html
92 pub struct BigNumContext
;
93 /// Reference to [`BigNumContext`]
95 /// [`BigNumContext`]: struct.BigNumContext.html
96 pub struct BigNumContextRef
;
100 /// Returns a new `BigNumContext`.
102 /// See OpenSSL documentation at [`BN_CTX_new`].
104 /// [`BN_CTX_new`]: https://www.openssl.org/docs/man1.1.0/crypto/BN_CTX_new.html
105 pub fn new() -> Result
<BigNumContext
, ErrorStack
> {
108 cvt_p(ffi
::BN_CTX_new()).map(BigNumContext
)
113 foreign_type_and_impl_send_sync
! {
114 type CType
= ffi
::BIGNUM
;
115 fn drop
= ffi
::BN_free
;
117 /// Dynamically sized large number impelementation
119 /// Perform large number mathematics. Create a new BigNum
120 /// with [`new`]. Perform standard mathematics on large numbers using
121 /// methods from [`Dref<Target = BigNumRef>`]
123 /// OpenSSL documenation at [`BN_new`].
125 /// [`new`]: struct.BigNum.html#method.new
126 /// [`Dref<Target = BigNumRef>`]: struct.BigNum.html#deref-methods
127 /// [`BN_new`]: https://www.openssl.org/docs/man1.1.0/crypto/BN_new.html
131 /// use openssl::bn::BigNum;
132 /// # use openssl::error::ErrorStack;
133 /// # fn bignums() -> Result< (), ErrorStack > {
134 /// let little_big = BigNum::from_u32(std::u32::MAX)?;
135 /// assert_eq!(*&little_big.num_bytes(), 4);
138 /// # fn main () { bignums(); }
141 /// Reference to a [`BigNum`]
143 /// [`BigNum`]: struct.BigNum.html
144 pub struct BigNumRef
;
148 /// Erases the memory used by this `BigNum`, resetting its value to 0.
150 /// This can be used to destroy sensitive data such as keys when they are no longer needed.
152 /// OpenSSL documentation at [`BN_clear`]
154 /// [`BN_clear`]: https://www.openssl.org/docs/man1.1.0/crypto/BN_clear.html
155 pub fn clear(&mut self) {
156 unsafe { ffi::BN_clear(self.as_ptr()) }
159 /// Adds a `u32` to `self`.
161 /// OpenSSL documentation at [`BN_add_word`]
163 /// [`BN_add_word`]: https://www.openssl.org/docs/man1.1.0/crypto/BN_add_word.html
164 pub fn add_word(&mut self, w
: u32) -> Result
<(), ErrorStack
> {
165 unsafe { cvt(ffi::BN_add_word(self.as_ptr(), w as ffi::BN_ULONG)).map(|_| ()) }
168 /// Subtracts a `u32` from `self`.
170 /// OpenSSL documentation at [`BN_sub_word`]
172 /// [`BN_sub_word`]: https://www.openssl.org/docs/man1.1.0/crypto/BN_sub_word.html
173 pub fn sub_word(&mut self, w
: u32) -> Result
<(), ErrorStack
> {
174 unsafe { cvt(ffi::BN_sub_word(self.as_ptr(), w as ffi::BN_ULONG)).map(|_| ()) }
177 /// Multiplies a `u32` by `self`.
179 /// OpenSSL documentation at [`BN_mul_word`]
181 /// [`BN_mul_word`]: https://www.openssl.org/docs/man1.1.0/crypto/BN_mul_word.html
182 pub fn mul_word(&mut self, w
: u32) -> Result
<(), ErrorStack
> {
183 unsafe { cvt(ffi::BN_mul_word(self.as_ptr(), w as ffi::BN_ULONG)).map(|_| ()) }
186 /// Divides `self` by a `u32`, returning the remainder.
188 /// OpenSSL documentation at [`BN_div_word`]
190 /// [`BN_div_word`]: https://www.openssl.org/docs/man1.1.0/crypto/BN_div_word.html
191 #[allow(clippy::identity_conversion)]
192 pub fn div_word(&mut self, w
: u32) -> Result
<u64, ErrorStack
> {
194 let r
= ffi
::BN_div_word(self.as_ptr(), w
.into());
195 if r
== ffi
::BN_ULONG
::max_value() {
196 Err(ErrorStack
::get())
203 /// Returns the result of `self` modulo `w`.
205 /// OpenSSL documentation at [`BN_mod_word`]
207 /// [`BN_mod_word`]: https://www.openssl.org/docs/man1.1.0/crypto/BN_mod_word.html
208 #[allow(clippy::identity_conversion)]
209 pub fn mod_word(&self, w
: u32) -> Result
<u64, ErrorStack
> {
211 let r
= ffi
::BN_mod_word(self.as_ptr(), w
.into());
212 if r
== ffi
::BN_ULONG
::max_value() {
213 Err(ErrorStack
::get())
220 /// Places a cryptographically-secure pseudo-random nonnegative
221 /// number less than `self` in `rnd`.
223 /// OpenSSL documentation at [`BN_rand_range`]
225 /// [`BN_rand_range`]: https://www.openssl.org/docs/man1.1.0/crypto/BN_rand_range.html
226 pub fn rand_range(&self, rnd
: &mut BigNumRef
) -> Result
<(), ErrorStack
> {
227 unsafe { cvt(ffi::BN_rand_range(rnd.as_ptr(), self.as_ptr())).map(|_| ()) }
230 /// The cryptographically weak counterpart to `rand_in_range`.
232 /// OpenSSL documentation at [`BN_pseudo_rand_range`]
234 /// [`BN_pseudo_rand_range`]: https://www.openssl.org/docs/man1.1.0/crypto/BN_pseudo_rand_range.html
235 pub fn pseudo_rand_range(&self, rnd
: &mut BigNumRef
) -> Result
<(), ErrorStack
> {
236 unsafe { cvt(ffi::BN_pseudo_rand_range(rnd.as_ptr(), self.as_ptr())).map(|_| ()) }
239 /// Sets bit `n`. Equivalent to `self |= (1 << n)`.
241 /// When setting a bit outside of `self`, it is expanded.
243 /// OpenSSL documentation at [`BN_set_bit`]
245 /// [`BN_set_bit`]: https://www.openssl.org/docs/man1.1.0/crypto/BN_set_bit.html
246 #[allow(clippy::identity_conversion)]
247 pub fn set_bit(&mut self, n
: i32) -> Result
<(), ErrorStack
> {
248 unsafe { cvt(ffi::BN_set_bit(self.as_ptr(), n.into())).map(|_| ()) }
251 /// Clears bit `n`, setting it to 0. Equivalent to `self &= ~(1 << n)`.
253 /// When clearing a bit outside of `self`, an error is returned.
255 /// OpenSSL documentation at [`BN_clear_bit`]
257 /// [`BN_clear_bit`]: https://www.openssl.org/docs/man1.1.0/crypto/BN_clear_bit.html
258 #[allow(clippy::identity_conversion)]
259 pub fn clear_bit(&mut self, n
: i32) -> Result
<(), ErrorStack
> {
260 unsafe { cvt(ffi::BN_clear_bit(self.as_ptr(), n.into())).map(|_| ()) }
263 /// Returns `true` if the `n`th bit of `self` is set to 1, `false` otherwise.
265 /// OpenSSL documentation at [`BN_is_bit_set`]
267 /// [`BN_is_bit_set`]: https://www.openssl.org/docs/man1.1.0/crypto/BN_is_bit_set.html
268 #[allow(clippy::identity_conversion)]
269 pub fn is_bit_set(&self, n
: i32) -> bool
{
270 unsafe { ffi::BN_is_bit_set(self.as_ptr(), n.into()) == 1 }
273 /// Truncates `self` to the lowest `n` bits.
275 /// An error occurs if `self` is already shorter than `n` bits.
277 /// OpenSSL documentation at [`BN_mask_bits`]
279 /// [`BN_mask_bits`]: https://www.openssl.org/docs/man1.1.0/crypto/BN_mask_bits.html
280 #[allow(clippy::identity_conversion)]
281 pub fn mask_bits(&mut self, n
: i32) -> Result
<(), ErrorStack
> {
282 unsafe { cvt(ffi::BN_mask_bits(self.as_ptr(), n.into())).map(|_| ()) }
285 /// Places `a << 1` in `self`. Equivalent to `self * 2`.
287 /// OpenSSL documentation at [`BN_lshift1`]
289 /// [`BN_lshift1`]: https://www.openssl.org/docs/man1.1.0/crypto/BN_lshift1.html
290 pub fn lshift1(&mut self, a
: &BigNumRef
) -> Result
<(), ErrorStack
> {
291 unsafe { cvt(ffi::BN_lshift1(self.as_ptr(), a.as_ptr())).map(|_| ()) }
294 /// Places `a >> 1` in `self`. Equivalent to `self / 2`.
296 /// OpenSSL documentation at [`BN_rshift1`]
298 /// [`BN_rshift1`]: https://www.openssl.org/docs/man1.1.0/crypto/BN_rshift1.html
299 pub fn rshift1(&mut self, a
: &BigNumRef
) -> Result
<(), ErrorStack
> {
300 unsafe { cvt(ffi::BN_rshift1(self.as_ptr(), a.as_ptr())).map(|_| ()) }
303 /// Places `a + b` in `self`. [`core::ops::Add`] is also implemented for `BigNumRef`.
305 /// OpenSSL documentation at [`BN_add`]
307 /// [`core::ops::Add`]: struct.BigNumRef.html#method.add
308 /// [`BN_add`]: https://www.openssl.org/docs/man1.1.0/crypto/BN_add.html
309 pub fn checked_add(&mut self, a
: &BigNumRef
, b
: &BigNumRef
) -> Result
<(), ErrorStack
> {
310 unsafe { cvt(ffi::BN_add(self.as_ptr(), a.as_ptr(), b.as_ptr())).map(|_| ()) }
313 /// Places `a - b` in `self`. [`core::ops::Sub`] is also implemented for `BigNumRef`.
315 /// OpenSSL documentation at [`BN_sub`]
317 /// [`core::ops::Sub`]: struct.BigNumRef.html#method.sub
318 /// [`BN_sub`]: https://www.openssl.org/docs/man1.1.0/crypto/BN_sub.html
319 pub fn checked_sub(&mut self, a
: &BigNumRef
, b
: &BigNumRef
) -> Result
<(), ErrorStack
> {
320 unsafe { cvt(ffi::BN_sub(self.as_ptr(), a.as_ptr(), b.as_ptr())).map(|_| ()) }
323 /// Places `a << n` in `self`. Equivalent to `a * 2 ^ n`.
325 /// OpenSSL documentation at [`BN_lshift`]
327 /// [`BN_lshift`]: https://www.openssl.org/docs/man1.1.0/crypto/BN_lshift.html
328 #[allow(clippy::identity_conversion)]
329 pub fn lshift(&mut self, a
: &BigNumRef
, n
: i32) -> Result
<(), ErrorStack
> {
330 unsafe { cvt(ffi::BN_lshift(self.as_ptr(), a.as_ptr(), n.into())).map(|_| ()) }
333 /// Places `a >> n` in `self`. Equivalent to `a / 2 ^ n`.
335 /// OpenSSL documentation at [`BN_rshift`]
337 /// [`BN_rshift`]: https://www.openssl.org/docs/man1.1.0/crypto/BN_rshift.html
338 #[allow(clippy::identity_conversion)]
339 pub fn rshift(&mut self, a
: &BigNumRef
, n
: i32) -> Result
<(), ErrorStack
> {
340 unsafe { cvt(ffi::BN_rshift(self.as_ptr(), a.as_ptr(), n.into())).map(|_| ()) }
343 /// Creates a new BigNum with the same value.
345 /// OpenSSL documentation at [`BN_dup`]
347 /// [`BN_dup`]: https://www.openssl.org/docs/man1.1.0/crypto/BN_dup.html
348 pub fn to_owned(&self) -> Result
<BigNum
, ErrorStack
> {
349 unsafe { cvt_p(ffi::BN_dup(self.as_ptr())).map(|b| BigNum::from_ptr(b)) }
352 /// Sets the sign of `self`. Pass true to set `self` to a negative. False sets
354 pub fn set_negative(&mut self, negative
: bool
) {
355 unsafe { ffi::BN_set_negative(self.as_ptr(), negative as c_int) }
358 /// Compare the absolute values of `self` and `oth`.
360 /// OpenSSL documentation at [`BN_ucmp`]
362 /// [`BN_ucmp`]: https://www.openssl.org/docs/man1.1.0/crypto/BN_ucmp.html
367 /// # use openssl::bn::BigNum;
368 /// # use std::cmp::Ordering;
369 /// let s = -BigNum::from_u32(8).unwrap();
370 /// let o = BigNum::from_u32(8).unwrap();
372 /// assert_eq!(s.ucmp(&o), Ordering::Equal);
374 pub fn ucmp(&self, oth
: &BigNumRef
) -> Ordering
{
375 unsafe { ffi::BN_ucmp(self.as_ptr(), oth.as_ptr()).cmp(&0) }
378 /// Returns `true` if `self` is negative.
379 pub fn is_negative(&self) -> bool
{
380 unsafe { BN_is_negative(self.as_ptr()) == 1 }
383 /// Returns the number of significant bits in `self`.
385 /// OpenSSL documentation at [`BN_num_bits`]
387 /// [`BN_num_bits`]: https://www.openssl.org/docs/man1.1.0/crypto/BN_num_bits.html
388 pub fn num_bits(&self) -> i32 {
389 unsafe { ffi::BN_num_bits(self.as_ptr()) as i32 }
392 /// Returns the size of `self` in bytes. Implemented natively.
393 pub fn num_bytes(&self) -> i32 {
394 (self.num_bits() + 7) / 8
397 /// Generates a cryptographically strong pseudo-random `BigNum`, placing it in `self`.
401 /// * `bits`: Length of the number in bits.
402 /// * `msb`: The desired properties of the most significant bit. See [`constants`].
403 /// * `odd`: If `true`, the generated number will be odd.
408 /// use openssl::bn::{BigNum, MsbOption};
409 /// use openssl::error::ErrorStack;
411 /// fn generate_random() -> Result< BigNum, ErrorStack > {
412 /// let mut big = BigNum::new()?;
414 /// // Generates a 128-bit odd random number
415 /// big.rand(128, MsbOption::MAYBE_ZERO, true);
420 /// OpenSSL documentation at [`BN_rand`]
422 /// [`constants`]: index.html#constants
423 /// [`BN_rand`]: https://www.openssl.org/docs/man1.1.0/crypto/BN_rand.html
424 #[allow(clippy::identity_conversion)]
425 pub fn rand(&mut self, bits
: i32, msb
: MsbOption
, odd
: bool
) -> Result
<(), ErrorStack
> {
437 /// The cryptographically weak counterpart to `rand`. Not suitable for key generation.
439 /// OpenSSL documentation at [`BN_psuedo_rand`]
441 /// [`BN_psuedo_rand`]: https://www.openssl.org/docs/man1.1.0/crypto/BN_pseudo_rand.html
442 #[allow(clippy::identity_conversion)]
443 pub fn pseudo_rand(&mut self, bits
: i32, msb
: MsbOption
, odd
: bool
) -> Result
<(), ErrorStack
> {
445 cvt(ffi
::BN_pseudo_rand(
455 /// Generates a prime number, placing it in `self`.
459 /// * `bits`: The length of the prime in bits (lower bound).
460 /// * `safe`: If true, returns a "safe" prime `p` so that `(p-1)/2` is also prime.
461 /// * `add`/`rem`: If `add` is set to `Some(add)`, `p % add == rem` will hold, where `p` is the
462 /// generated prime and `rem` is `1` if not specified (`None`).
467 /// use openssl::bn::BigNum;
468 /// use openssl::error::ErrorStack;
470 /// fn generate_weak_prime() -> Result< BigNum, ErrorStack > {
471 /// let mut big = BigNum::new()?;
473 /// // Generates a 128-bit simple prime number
474 /// big.generate_prime(128, false, None, None);
479 /// OpenSSL documentation at [`BN_generate_prime_ex`]
481 /// [`BN_generate_prime_ex`]: https://www.openssl.org/docs/man1.1.0/crypto/BN_generate_prime_ex.html
482 pub fn generate_prime(
486 add
: Option
<&BigNumRef
>,
487 rem
: Option
<&BigNumRef
>,
488 ) -> Result
<(), ErrorStack
> {
490 cvt(ffi
::BN_generate_prime_ex(
494 add
.map(|n
| n
.as_ptr()).unwrap_or(ptr
::null_mut()),
495 rem
.map(|n
| n
.as_ptr()).unwrap_or(ptr
::null_mut()),
502 /// Places the result of `a * b` in `self`.
503 /// [`core::ops::Mul`] is also implemented for `BigNumRef`.
505 /// OpenSSL documentation at [`BN_mul`]
507 /// [`core::ops::Mul`]: struct.BigNumRef.html#method.mul
508 /// [`BN_mul`]: https://www.openssl.org/docs/man1.1.0/crypto/BN_mul.html
513 ctx
: &mut BigNumContextRef
,
514 ) -> Result
<(), ErrorStack
> {
526 /// Places the result of `a / b` in `self`. The remainder is discarded.
527 /// [`core::ops::Div`] is also implemented for `BigNumRef`.
529 /// OpenSSL documentation at [`BN_div`]
531 /// [`core::ops::Div`]: struct.BigNumRef.html#method.div
532 /// [`BN_div`]: https://www.openssl.org/docs/man1.1.0/crypto/BN_div.html
537 ctx
: &mut BigNumContextRef
,
538 ) -> Result
<(), ErrorStack
> {
551 /// Places the result of `a % b` in `self`.
553 /// OpenSSL documentation at [`BN_div`]
555 /// [`BN_div`]: https://www.openssl.org/docs/man1.1.0/crypto/BN_div.html
560 ctx
: &mut BigNumContextRef
,
561 ) -> Result
<(), ErrorStack
> {
574 /// Places the result of `a / b` in `self` and `a % b` in `rem`.
576 /// OpenSSL documentation at [`BN_div`]
578 /// [`BN_div`]: https://www.openssl.org/docs/man1.1.0/crypto/BN_div.html
584 ctx
: &mut BigNumContextRef
,
585 ) -> Result
<(), ErrorStack
> {
598 /// Places the result of `a²` in `self`.
600 /// OpenSSL documentation at [`BN_sqr`]
602 /// [`BN_sqr`]: https://www.openssl.org/docs/man1.1.0/crypto/BN_sqr.html
603 pub fn sqr(&mut self, a
: &BigNumRef
, ctx
: &mut BigNumContextRef
) -> Result
<(), ErrorStack
> {
604 unsafe { cvt(ffi::BN_sqr(self.as_ptr(), a.as_ptr(), ctx.as_ptr())).map(|_| ()) }
607 /// Places the result of `a mod m` in `self`. As opposed to `div_rem`
608 /// the result is non-negative.
610 /// OpenSSL documentation at [`BN_nnmod`]
612 /// [`BN_nnmod`]: https://www.openssl.org/docs/man1.1.0/crypto/BN_nnmod.html
617 ctx
: &mut BigNumContextRef
,
618 ) -> Result
<(), ErrorStack
> {
630 /// Places the result of `(a + b) mod m` in `self`.
632 /// OpenSSL documentation at [`BN_mod_add`]
634 /// [`BN_mod_add`]: https://www.openssl.org/docs/man1.1.0/crypto/BN_mod_add.html
640 ctx
: &mut BigNumContextRef
,
641 ) -> Result
<(), ErrorStack
> {
654 /// Places the result of `(a - b) mod m` in `self`.
656 /// OpenSSL documentation at [`BN_mod_sub`]
658 /// [`BN_mod_sub`]: https://www.openssl.org/docs/man1.1.0/crypto/BN_mod_sub.html
664 ctx
: &mut BigNumContextRef
,
665 ) -> Result
<(), ErrorStack
> {
678 /// Places the result of `(a * b) mod m` in `self`.
680 /// OpenSSL documentation at [`BN_mod_mul`]
682 /// [`BN_mod_mul`]: https://www.openssl.org/docs/man1.1.0/crypto/BN_mod_mul.html
688 ctx
: &mut BigNumContextRef
,
689 ) -> Result
<(), ErrorStack
> {
702 /// Places the result of `a² mod m` in `self`.
704 /// OpenSSL documentation at [`BN_mod_sqr`]
706 /// [`BN_mod_sqr`]: https://www.openssl.org/docs/man1.1.0/crypto/BN_mod_sqr.html
711 ctx
: &mut BigNumContextRef
,
712 ) -> Result
<(), ErrorStack
> {
724 /// Places the result of `a^p` in `self`.
726 /// OpenSSL documentation at [`BN_exp`]
728 /// [`BN_exp`]: https://www.openssl.org/docs/man1.1.0/crypto/BN_exp.html
733 ctx
: &mut BigNumContextRef
,
734 ) -> Result
<(), ErrorStack
> {
746 /// Places the result of `a^p mod m` in `self`.
748 /// OpenSSL documentation at [`BN_mod_exp`]
750 /// [`BN_mod_exp`]: https://www.openssl.org/docs/man1.1.0/crypto/BN_mod_exp.html
756 ctx
: &mut BigNumContextRef
,
757 ) -> Result
<(), ErrorStack
> {
770 /// Places the inverse of `a` modulo `n` in `self`.
775 ctx
: &mut BigNumContextRef
,
776 ) -> Result
<(), ErrorStack
> {
778 cvt_p(ffi
::BN_mod_inverse(
788 /// Places the greatest common denominator of `a` and `b` in `self`.
790 /// OpenSSL documentation at [`BN_gcd`]
792 /// [`BN_gcd`]: https://www.openssl.org/docs/man1.1.0/crypto/BN_gcd.html
797 ctx
: &mut BigNumContextRef
,
798 ) -> Result
<(), ErrorStack
> {
810 /// Checks whether `self` is prime.
812 /// Performs a Miller-Rabin probabilistic primality test with `checks` iterations.
814 /// OpenSSL documentation at [`BN_is_prime_ex`]
816 /// [`BN_is_prime_ex`]: https://www.openssl.org/docs/man1.1.0/crypto/BN_is_prime_ex.html
820 /// Returns `true` if `self` is prime with an error probability of less than `0.25 ^ checks`.
821 #[allow(clippy::identity_conversion)]
822 pub fn is_prime(&self, checks
: i32, ctx
: &mut BigNumContextRef
) -> Result
<bool
, ErrorStack
> {
824 cvt_n(ffi
::BN_is_prime_ex(
834 /// Checks whether `self` is prime with optional trial division.
836 /// If `do_trial_division` is `true`, first performs trial division by a number of small primes.
837 /// Then, like `is_prime`, performs a Miller-Rabin probabilistic primality test with `checks`
840 /// OpenSSL documentation at [`BN_is_prime_fasttest_ex`]
842 /// [`BN_is_prime_fasttest_ex`]: https://www.openssl.org/docs/man1.1.0/crypto/BN_is_prime_fasttest_ex.html
846 /// Returns `true` if `self` is prime with an error probability of less than `0.25 ^ checks`.
847 #[allow(clippy::identity_conversion)]
848 pub fn is_prime_fasttest(
851 ctx
: &mut BigNumContextRef
,
852 do_trial_division
: bool
,
853 ) -> Result
<bool
, ErrorStack
> {
855 cvt_n(ffi
::BN_is_prime_fasttest_ex(
859 do_trial_division
as c_int
,
866 /// Returns a big-endian byte vector representation of the absolute value of `self`.
868 /// `self` can be recreated by using `from_slice`.
871 /// # use openssl::bn::BigNum;
872 /// let s = -BigNum::from_u32(4543).unwrap();
873 /// let r = BigNum::from_u32(4543).unwrap();
875 /// let s_vec = s.to_vec();
876 /// assert_eq!(BigNum::from_slice(&s_vec).unwrap(), r);
878 pub fn to_vec(&self) -> Vec
<u8> {
879 let size
= self.num_bytes() as usize;
880 let mut v
= Vec
::with_capacity(size
);
882 ffi
::BN_bn2bin(self.as_ptr(), v
.as_mut_ptr());
888 /// Returns a decimal string representation of `self`.
891 /// # use openssl::bn::BigNum;
892 /// let s = -BigNum::from_u32(12345).unwrap();
894 /// assert_eq!(&**s.to_dec_str().unwrap(), "-12345");
896 pub fn to_dec_str(&self) -> Result
<OpensslString
, ErrorStack
> {
898 let buf
= cvt_p(ffi
::BN_bn2dec(self.as_ptr()))?
;
899 Ok(OpensslString
::from_ptr(buf
))
903 /// Returns a hexadecimal string representation of `self`.
906 /// # use openssl::bn::BigNum;
907 /// let s = -BigNum::from_u32(0x99ff).unwrap();
909 /// assert_eq!(&**s.to_hex_str().unwrap(), "-99FF");
911 pub fn to_hex_str(&self) -> Result
<OpensslString
, ErrorStack
> {
913 let buf
= cvt_p(ffi
::BN_bn2hex(self.as_ptr()))?
;
914 Ok(OpensslString
::from_ptr(buf
))
918 /// Returns an `Asn1Integer` containing the value of `self`.
919 pub fn to_asn1_integer(&self) -> Result
<Asn1Integer
, ErrorStack
> {
921 cvt_p(ffi
::BN_to_ASN1_INTEGER(self.as_ptr(), ptr
::null_mut()))
922 .map(|p
| Asn1Integer
::from_ptr(p
))
928 /// Creates a new `BigNum` with the value 0.
929 pub fn new() -> Result
<BigNum
, ErrorStack
> {
932 let v
= cvt_p(ffi
::BN_new())?
;
933 Ok(BigNum
::from_ptr(v
))
937 /// Creates a new `BigNum` with the given value.
939 /// OpenSSL documentation at [`BN_set_word`]
941 /// [`BN_set_word`]: https://www.openssl.org/docs/man1.1.0/crypto/BN_set_word.html
942 pub fn from_u32(n
: u32) -> Result
<BigNum
, ErrorStack
> {
943 BigNum
::new().and_then(|v
| unsafe {
944 cvt(ffi
::BN_set_word(v
.as_ptr(), n
as ffi
::BN_ULONG
)).map(|_
| v
)
948 /// Creates a `BigNum` from a decimal string.
950 /// OpenSSL documentation at [`BN_dec2bn`]
952 /// [`BN_dec2bn`]: https://www.openssl.org/docs/man1.1.0/crypto/BN_dec2bn.html
953 pub fn from_dec_str(s
: &str) -> Result
<BigNum
, ErrorStack
> {
956 let c_str
= CString
::new(s
.as_bytes()).unwrap();
957 let mut bn
= ptr
::null_mut();
958 cvt(ffi
::BN_dec2bn(&mut bn
, c_str
.as_ptr() as *const _
))?
;
959 Ok(BigNum
::from_ptr(bn
))
963 /// Creates a `BigNum` from a hexadecimal string.
965 /// OpenSSL documentation at [`BN_hex2bn`]
967 /// [`BN_hex2bn`]: https://www.openssl.org/docs/man1.1.0/crypto/BN_hex2bn.html
968 pub fn from_hex_str(s
: &str) -> Result
<BigNum
, ErrorStack
> {
971 let c_str
= CString
::new(s
.as_bytes()).unwrap();
972 let mut bn
= ptr
::null_mut();
973 cvt(ffi
::BN_hex2bn(&mut bn
, c_str
.as_ptr() as *const _
))?
;
974 Ok(BigNum
::from_ptr(bn
))
978 /// Returns a constant used in IKE as defined in [`RFC 2409`]. This prime number is in
979 /// the order of magnitude of `2 ^ 768`. This number is used during calculated key
980 /// exchanges such as Diffie-Hellman. This number is labeled Oakley group id 1.
982 /// OpenSSL documentation at [`BN_get_rfc2409_prime_768`]
984 /// [`RFC 2409`]: https://tools.ietf.org/html/rfc2409#page-21
985 /// [`BN_get_rfc2409_prime_768`]: https://www.openssl.org/docs/man1.1.0/crypto/BN_get_rfc2409_prime_768.html
986 pub fn get_rfc2409_prime_768() -> Result
<BigNum
, ErrorStack
> {
989 cvt_p(BN_get_rfc2409_prime_768(ptr
::null_mut())).map(BigNum
)
993 /// Returns a constant used in IKE as defined in [`RFC 2409`]. This prime number is in
994 /// the order of magnitude of `2 ^ 1024`. This number is used during calculated key
995 /// exchanges such as Diffie-Hellman. This number is labeled Oakly group 2.
997 /// OpenSSL documentation at [`BN_get_rfc2409_prime_1024`]
999 /// [`RFC 2409`]: https://tools.ietf.org/html/rfc2409#page-21
1000 /// [`BN_get_rfc2409_prime_1024`]: https://www.openssl.org/docs/man1.1.0/crypto/BN_get_rfc2409_prime_1024.html
1001 pub fn get_rfc2409_prime_1024() -> Result
<BigNum
, ErrorStack
> {
1004 cvt_p(BN_get_rfc2409_prime_1024(ptr
::null_mut())).map(BigNum
)
1008 /// Returns a constant used in IKE as defined in [`RFC 3526`]. The prime is in the order
1009 /// of magnitude of `2 ^ 1536`. This number is used during calculated key
1010 /// exchanges such as Diffie-Hellman. This number is labeled MODP group 5.
1012 /// OpenSSL documentation at [`BN_get_rfc3526_prime_1536`]
1014 /// [`RFC 3526`]: https://tools.ietf.org/html/rfc3526#page-3
1015 /// [`BN_get_rfc3526_prime_1536`]: https://www.openssl.org/docs/man1.1.0/crypto/BN_get_rfc3526_prime_1536.html
1016 pub fn get_rfc3526_prime_1536() -> Result
<BigNum
, ErrorStack
> {
1019 cvt_p(BN_get_rfc3526_prime_1536(ptr
::null_mut())).map(BigNum
)
1023 /// Returns a constant used in IKE as defined in [`RFC 3526`]. The prime is in the order
1024 /// of magnitude of `2 ^ 2048`. This number is used during calculated key
1025 /// exchanges such as Diffie-Hellman. This number is labeled MODP group 14.
1027 /// OpenSSL documentation at [`BN_get_rfc3526_prime_2048`]
1029 /// [`RFC 3526`]: https://tools.ietf.org/html/rfc3526#page-3
1030 /// [`BN_get_rfc3526_prime_2048`]: https://www.openssl.org/docs/man1.1.0/crypto/BN_get_rfc3526_prime_2048.html
1031 pub fn get_rfc3526_prime_2048() -> Result
<BigNum
, ErrorStack
> {
1034 cvt_p(BN_get_rfc3526_prime_2048(ptr
::null_mut())).map(BigNum
)
1038 /// Returns a constant used in IKE as defined in [`RFC 3526`]. The prime is in the order
1039 /// of magnitude of `2 ^ 3072`. This number is used during calculated key
1040 /// exchanges such as Diffie-Hellman. This number is labeled MODP group 15.
1042 /// OpenSSL documentation at [`BN_get_rfc3526_prime_3072`]
1044 /// [`RFC 3526`]: https://tools.ietf.org/html/rfc3526#page-4
1045 /// [`BN_get_rfc3526_prime_3072`]: https://www.openssl.org/docs/man1.1.0/crypto/BN_get_rfc3526_prime_3072.html
1046 pub fn get_rfc3526_prime_3072() -> Result
<BigNum
, ErrorStack
> {
1049 cvt_p(BN_get_rfc3526_prime_3072(ptr
::null_mut())).map(BigNum
)
1053 /// Returns a constant used in IKE as defined in [`RFC 3526`]. The prime is in the order
1054 /// of magnitude of `2 ^ 4096`. This number is used during calculated key
1055 /// exchanges such as Diffie-Hellman. This number is labeled MODP group 16.
1057 /// OpenSSL documentation at [`BN_get_rfc3526_prime_4096`]
1059 /// [`RFC 3526`]: https://tools.ietf.org/html/rfc3526#page-4
1060 /// [`BN_get_rfc3526_prime_4096`]: https://www.openssl.org/docs/man1.1.0/crypto/BN_get_rfc3526_prime_4096.html
1061 pub fn get_rfc3526_prime_4096() -> Result
<BigNum
, ErrorStack
> {
1064 cvt_p(BN_get_rfc3526_prime_4096(ptr
::null_mut())).map(BigNum
)
1068 /// Returns a constant used in IKE as defined in [`RFC 3526`]. The prime is in the order
1069 /// of magnitude of `2 ^ 6144`. This number is used during calculated key
1070 /// exchanges such as Diffie-Hellman. This number is labeled MODP group 17.
1072 /// OpenSSL documentation at [`BN_get_rfc3526_prime_6144`]
1074 /// [`RFC 3526`]: https://tools.ietf.org/html/rfc3526#page-6
1075 /// [`BN_get_rfc3526_prime_6144`]: https://www.openssl.org/docs/man1.1.0/crypto/BN_get_rfc3526_prime_6144.html
1076 pub fn get_rfc3526_prime_6144() -> Result
<BigNum
, ErrorStack
> {
1079 cvt_p(BN_get_rfc3526_prime_6144(ptr
::null_mut())).map(BigNum
)
1083 /// Returns a constant used in IKE as defined in [`RFC 3526`]. The prime is in the order
1084 /// of magnitude of `2 ^ 8192`. This number is used during calculated key
1085 /// exchanges such as Diffie-Hellman. This number is labeled MODP group 18.
1087 /// OpenSSL documentation at [`BN_get_rfc3526_prime_8192`]
1089 /// [`RFC 3526`]: https://tools.ietf.org/html/rfc3526#page-6
1090 /// [`BN_get_rfc3526_prime_8192`]: https://www.openssl.org/docs/man1.1.0/crypto/BN_get_rfc3526_prime_8192.html
1091 pub fn get_rfc3526_prime_8192() -> Result
<BigNum
, ErrorStack
> {
1094 cvt_p(BN_get_rfc3526_prime_8192(ptr
::null_mut())).map(BigNum
)
1098 /// Creates a new `BigNum` from an unsigned, big-endian encoded number of arbitrary length.
1100 /// OpenSSL documentation at [`BN_bin2bn`]
1102 /// [`BN_bin2bn`]: https://www.openssl.org/docs/man1.1.0/crypto/BN_bin2bn.html
1105 /// # use openssl::bn::BigNum;
1106 /// let bignum = BigNum::from_slice(&[0x12, 0x00, 0x34]).unwrap();
1108 /// assert_eq!(bignum, BigNum::from_u32(0x120034).unwrap());
1110 pub fn from_slice(n
: &[u8]) -> Result
<BigNum
, ErrorStack
> {
1113 assert
!(n
.len() <= c_int
::max_value() as usize);
1114 cvt_p(ffi
::BN_bin2bn(
1119 .map(|p
| BigNum
::from_ptr(p
))
1124 impl fmt
::Debug
for BigNumRef
{
1125 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
1126 match self.to_dec_str() {
1127 Ok(s
) => f
.write_str(&s
),
1128 Err(e
) => Err(e
.into()),
1133 impl fmt
::Debug
for BigNum
{
1134 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
1135 match self.to_dec_str() {
1136 Ok(s
) => f
.write_str(&s
),
1137 Err(e
) => Err(e
.into()),
1142 impl fmt
::Display
for BigNumRef
{
1143 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
1144 match self.to_dec_str() {
1145 Ok(s
) => f
.write_str(&s
),
1146 Err(e
) => Err(e
.into()),
1151 impl fmt
::Display
for BigNum
{
1152 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
1153 match self.to_dec_str() {
1154 Ok(s
) => f
.write_str(&s
),
1155 Err(e
) => Err(e
.into()),
1160 impl PartialEq
<BigNumRef
> for BigNumRef
{
1161 fn eq(&self, oth
: &BigNumRef
) -> bool
{
1162 self.cmp(oth
) == Ordering
::Equal
1166 impl PartialEq
<BigNum
> for BigNumRef
{
1167 fn eq(&self, oth
: &BigNum
) -> bool
{
1168 self.eq(oth
.deref())
1172 impl Eq
for BigNumRef {}
1174 impl PartialEq
for BigNum
{
1175 fn eq(&self, oth
: &BigNum
) -> bool
{
1176 self.deref().eq(oth
)
1180 impl PartialEq
<BigNumRef
> for BigNum
{
1181 fn eq(&self, oth
: &BigNumRef
) -> bool
{
1182 self.deref().eq(oth
)
1186 impl Eq
for BigNum {}
1188 impl PartialOrd
<BigNumRef
> for BigNumRef
{
1189 fn partial_cmp(&self, oth
: &BigNumRef
) -> Option
<Ordering
> {
1194 impl PartialOrd
<BigNum
> for BigNumRef
{
1195 fn partial_cmp(&self, oth
: &BigNum
) -> Option
<Ordering
> {
1196 Some(self.cmp(oth
.deref()))
1200 impl Ord
for BigNumRef
{
1201 fn cmp(&self, oth
: &BigNumRef
) -> Ordering
{
1202 unsafe { ffi::BN_cmp(self.as_ptr(), oth.as_ptr()).cmp(&0) }
1206 impl PartialOrd
for BigNum
{
1207 fn partial_cmp(&self, oth
: &BigNum
) -> Option
<Ordering
> {
1208 self.deref().partial_cmp(oth
.deref())
1212 impl PartialOrd
<BigNumRef
> for BigNum
{
1213 fn partial_cmp(&self, oth
: &BigNumRef
) -> Option
<Ordering
> {
1214 self.deref().partial_cmp(oth
)
1218 impl Ord
for BigNum
{
1219 fn cmp(&self, oth
: &BigNum
) -> Ordering
{
1220 self.deref().cmp(oth
.deref())
1224 macro_rules
! delegate
{
1225 ($t
:ident
, $m
:ident
) => {
1226 impl<'a
, 'b
> $t
<&'b BigNum
> for &'a BigNumRef
{
1227 type Output
= BigNum
;
1229 fn $
m(self, oth
: &BigNum
) -> BigNum
{
1230 $t
::$
m(self, oth
.deref())
1234 impl<'a
, 'b
> $t
<&'b BigNumRef
> for &'a BigNum
{
1235 type Output
= BigNum
;
1237 fn $
m(self, oth
: &BigNumRef
) -> BigNum
{
1238 $t
::$
m(self.deref(), oth
)
1242 impl<'a
, 'b
> $t
<&'b BigNum
> for &'a BigNum
{
1243 type Output
= BigNum
;
1245 fn $
m(self, oth
: &BigNum
) -> BigNum
{
1246 $t
::$
m(self.deref(), oth
.deref())
1252 impl<'a
, 'b
> Add
<&'b BigNumRef
> for &'a BigNumRef
{
1253 type Output
= BigNum
;
1255 fn add(self, oth
: &BigNumRef
) -> BigNum
{
1256 let mut r
= BigNum
::new().unwrap();
1257 r
.checked_add(self, oth
).unwrap();
1262 delegate
!(Add
, add
);
1264 impl<'a
, 'b
> Sub
<&'b BigNumRef
> for &'a BigNumRef
{
1265 type Output
= BigNum
;
1267 fn sub(self, oth
: &BigNumRef
) -> BigNum
{
1268 let mut r
= BigNum
::new().unwrap();
1269 r
.checked_sub(self, oth
).unwrap();
1274 delegate
!(Sub
, sub
);
1276 impl<'a
, 'b
> Mul
<&'b BigNumRef
> for &'a BigNumRef
{
1277 type Output
= BigNum
;
1279 fn mul(self, oth
: &BigNumRef
) -> BigNum
{
1280 let mut ctx
= BigNumContext
::new().unwrap();
1281 let mut r
= BigNum
::new().unwrap();
1282 r
.checked_mul(self, oth
, &mut ctx
).unwrap();
1287 delegate
!(Mul
, mul
);
1289 impl<'a
, 'b
> Div
<&'b BigNumRef
> for &'a BigNumRef
{
1290 type Output
= BigNum
;
1292 fn div(self, oth
: &'b BigNumRef
) -> BigNum
{
1293 let mut ctx
= BigNumContext
::new().unwrap();
1294 let mut r
= BigNum
::new().unwrap();
1295 r
.checked_div(self, oth
, &mut ctx
).unwrap();
1300 delegate
!(Div
, div
);
1302 impl<'a
, 'b
> Rem
<&'b BigNumRef
> for &'a BigNumRef
{
1303 type Output
= BigNum
;
1305 fn rem(self, oth
: &'b BigNumRef
) -> BigNum
{
1306 let mut ctx
= BigNumContext
::new().unwrap();
1307 let mut r
= BigNum
::new().unwrap();
1308 r
.checked_rem(self, oth
, &mut ctx
).unwrap();
1313 delegate
!(Rem
, rem
);
1315 impl<'a
> Shl
<i32> for &'a BigNumRef
{
1316 type Output
= BigNum
;
1318 fn shl(self, n
: i32) -> BigNum
{
1319 let mut r
= BigNum
::new().unwrap();
1320 r
.lshift(self, n
).unwrap();
1325 impl<'a
> Shl
<i32> for &'a BigNum
{
1326 type Output
= BigNum
;
1328 fn shl(self, n
: i32) -> BigNum
{
1333 impl<'a
> Shr
<i32> for &'a BigNumRef
{
1334 type Output
= BigNum
;
1336 fn shr(self, n
: i32) -> BigNum
{
1337 let mut r
= BigNum
::new().unwrap();
1338 r
.rshift(self, n
).unwrap();
1343 impl<'a
> Shr
<i32> for &'a BigNum
{
1344 type Output
= BigNum
;
1346 fn shr(self, n
: i32) -> BigNum
{
1351 impl<'a
> Neg
for &'a BigNumRef
{
1352 type Output
= BigNum
;
1354 fn neg(self) -> BigNum
{
1355 self.to_owned().unwrap().neg()
1359 impl<'a
> Neg
for &'a BigNum
{
1360 type Output
= BigNum
;
1362 fn neg(self) -> BigNum
{
1367 impl Neg
for BigNum
{
1368 type Output
= BigNum
;
1370 fn neg(mut self) -> BigNum
{
1371 let negative
= self.is_negative();
1372 self.set_negative(!negative
);
1379 use bn
::{BigNum, BigNumContext}
;
1382 fn test_to_from_slice() {
1383 let v0
= BigNum
::from_u32(10_203_004).unwrap();
1384 let vec
= v0
.to_vec();
1385 let v1
= BigNum
::from_slice(&vec
).unwrap();
1391 fn test_negation() {
1392 let a
= BigNum
::from_u32(909_829_283).unwrap();
1394 assert
!(!a
.is_negative());
1395 assert
!((-a
).is_negative());
1400 let a
= BigNum
::from_u32(909_829_283).unwrap();
1402 assert_eq
!(a
, &(&a
<< 1) >> 1);
1406 fn test_rand_range() {
1407 let range
= BigNum
::from_u32(909_829_283).unwrap();
1408 let mut result
= BigNum
::from_dec_str(&range
.to_dec_str().unwrap()).unwrap();
1409 range
.rand_range(&mut result
).unwrap();
1410 assert
!(result
>= BigNum
::from_u32(0).unwrap() && result
< range
);
1414 fn test_pseudo_rand_range() {
1415 let range
= BigNum
::from_u32(909_829_283).unwrap();
1416 let mut result
= BigNum
::from_dec_str(&range
.to_dec_str().unwrap()).unwrap();
1417 range
.pseudo_rand_range(&mut result
).unwrap();
1418 assert
!(result
>= BigNum
::from_u32(0).unwrap() && result
< range
);
1422 fn test_prime_numbers() {
1423 let a
= BigNum
::from_u32(19_029_017).unwrap();
1424 let mut p
= BigNum
::new().unwrap();
1425 p
.generate_prime(128, true, None
, Some(&a
)).unwrap();
1427 let mut ctx
= BigNumContext
::new().unwrap();
1428 assert
!(p
.is_prime(100, &mut ctx
).unwrap());
1429 assert
!(p
.is_prime_fasttest(100, &mut ctx
, true).unwrap());