2023-05-02 15:19:29 +02:00
|
|
|
#![allow(dead_code)]
|
2023-05-02 14:05:36 +02:00
|
|
|
|
2023-05-02 15:19:29 +02:00
|
|
|
use num_bigint::BigInt;
|
2023-05-02 14:05:36 +02:00
|
|
|
|
|
|
|
/// works, but is forbidden for class
|
|
|
|
pub fn calc_exp_in_field_lib(
|
|
|
|
base: BigInt,
|
|
|
|
exp: BigInt,
|
|
|
|
field: BigInt) -> BigInt {
|
|
|
|
base.modpow(&exp, &field)
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2023-05-02 15:17:17 +02:00
|
|
|
* modular exponentiation algorithm with big numbers.
|
|
|
|
*
|
2023-05-02 14:05:36 +02:00
|
|
|
* Umwandlung des Exponenten k in die zugehörige Binärdarstellung.
|
|
|
|
* Ersetzen jeder 0 durch Q und jeder 1 durch QM.
|
|
|
|
* Nun wird Q als Anweisung zum Quadrieren und M als Anweisung zum Multiplizieren aufgefasst.
|
|
|
|
* Somit bildet die resultierende Zeichenkette von links nach rechts gelesen eine Vorschrift zur Berechnung von x k .
|
|
|
|
* Man beginne mit 1, quadriere für jedes gelesene Q das bisherige Zwischenergebnis und
|
|
|
|
* multipliziere es für jedes gelesene M mit x .
|
|
|
|
*/
|
2023-05-02 15:17:17 +02:00
|
|
|
pub fn modular_exponentiation(
|
2023-05-02 14:05:36 +02:00
|
|
|
base: BigInt,
|
2023-05-02 15:17:17 +02:00
|
|
|
orig_exp: BigInt,
|
2023-05-02 14:05:36 +02:00
|
|
|
field: BigInt) -> BigInt {
|
2023-05-02 15:17:17 +02:00
|
|
|
let binary_repr = orig_exp.to_bytes_be();
|
2023-05-02 14:05:36 +02:00
|
|
|
|
|
|
|
let instructions: Vec<bool> = bytes_to_bools(&binary_repr.1);
|
|
|
|
|
2023-05-02 15:17:17 +02:00
|
|
|
let mut exp = BigInt::from(1);
|
|
|
|
for instr in instructions {
|
|
|
|
if instr {
|
|
|
|
// square
|
|
|
|
exp = (exp.pow(2) * &base) % &field;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
// square and multiply
|
|
|
|
exp = exp.pow(2) % &field;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return exp;
|
2023-05-02 14:05:36 +02:00
|
|
|
}
|
|
|
|
|
2023-05-02 15:17:17 +02:00
|
|
|
// Vec<u8> to Vec<bool> ( binary representation interpreted otherwise )
|
2023-05-02 14:05:36 +02:00
|
|
|
fn bytes_to_bools(bytes: &Vec<u8>) -> Vec<bool> {
|
|
|
|
let mut result: Vec<bool> = Vec::new();
|
|
|
|
for byte in bytes {
|
|
|
|
for c in format!("{:b}", byte).chars() {
|
|
|
|
result.push(c == '1');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
result
|
|
|
|
}
|
|
|
|
|
|
|
|
fn dump_bin(bytes: &Vec<u8>) {
|
|
|
|
for byte in bytes.iter() {
|
|
|
|
println!("{:#08b}\t| {:#02x}", byte, byte);
|
|
|
|
}
|
|
|
|
print!("0b");
|
|
|
|
for byte in bytes.iter() {
|
|
|
|
print!("{:08b}", byte);
|
|
|
|
}
|
|
|
|
println!();
|
|
|
|
|
|
|
|
}
|