work on gallois sqrt and a small pbox
This commit is contained in:
parent
c3ccd7701d
commit
c68885ecbf
|
@ -1,7 +1,7 @@
|
|||
[package]
|
||||
name = "plexcryptool"
|
||||
authors = ["Christoph J. Scherr <software@cscherr.de>"]
|
||||
version = "0.2.4"
|
||||
version = "0.2.5"
|
||||
edition = "2021"
|
||||
readme = "README.md"
|
||||
description = "Various tools for use with math and cryptology, includes executable and a library."
|
||||
|
|
|
@ -1,2 +1 @@
|
|||
from .plexcryptool import *
|
||||
from . import scripts as scripts
|
||||
|
|
|
@ -7,22 +7,24 @@
|
|||
/// License: MIT
|
||||
/// Source: <https://git.cscherr.de/PlexSheep/plexcryptool/>
|
||||
|
||||
/**
|
||||
* Pythons bit operations are trash, so I made a rust lib for that.
|
||||
*/
|
||||
pub mod pbox6;
|
||||
|
||||
use pyo3::prelude::*;
|
||||
|
||||
/// rotate 32 bit left
|
||||
#[pyfunction]
|
||||
pub fn rotl32 (value: u32, count: u32) -> u32 {
|
||||
value.rotate_left(count as u32)
|
||||
}
|
||||
|
||||
/// rotate 32 bit left
|
||||
#[pyfunction]
|
||||
pub fn rotr32 (value: u32, count: u32) -> u32 {
|
||||
value.rotate_right(count as u32)
|
||||
}
|
||||
|
||||
/// simple xor
|
||||
#[pyfunction]
|
||||
pub fn xor(a: u128, b: u128) -> u128 {
|
||||
a | b
|
||||
a ^ b
|
||||
}
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
/// # pbox 6
|
||||
///
|
||||
/// This module contains a simple 8 bit pbox.
|
||||
///
|
||||
/// ___
|
||||
/// Author: Christoph J. Scherr <software@cscherr.de>
|
||||
/// License: MIT
|
||||
/// Source: <https://git.cscherr.de/PlexSheep/plexcryptool/>
|
||||
|
||||
use pyo3::prelude::*;
|
||||
|
||||
#[test]
|
||||
fn test_pbox6() {
|
||||
assert_eq!(pbox6(0b11110000), 0b10110100);
|
||||
}
|
||||
|
||||
#[pyfunction]
|
||||
/// Basic 8 bit pbox for an assignment
|
||||
pub fn pbox6(n: u8) -> u8 {
|
||||
return (n & 0b10101010) | ((n & 0b01010100) >> 2 ) | ((n & 1) << 7);
|
||||
}
|
|
@ -118,7 +118,7 @@ pub enum GalloisActions {
|
|||
#[derive(Args, Clone, Debug, PartialEq, Eq)]
|
||||
pub struct GalloisSqrtArgs {
|
||||
#[clap(value_parser=maybe_hex::<u128>)]
|
||||
pub n: u128,
|
||||
pub a: u128,
|
||||
}
|
||||
|
||||
#[derive(Args, Clone, Debug, PartialEq, Eq)]
|
||||
|
@ -137,7 +137,11 @@ pub enum BinaryActions {
|
|||
/// bit rotation/circular shifting (only 32bit)
|
||||
#[command(name="rotate")]
|
||||
Rotate(RotateArgs),
|
||||
Xor(XorArgs)
|
||||
/// regular binary xor
|
||||
Xor(XorArgs),
|
||||
/// use a pbox
|
||||
Pbox(PboxArgs),
|
||||
|
||||
}
|
||||
|
||||
#[derive(Args, Clone, Debug, PartialEq, Eq)]
|
||||
|
@ -158,6 +162,12 @@ pub struct XorArgs {
|
|||
pub b: u128,
|
||||
}
|
||||
|
||||
#[derive(Args, Clone, Debug, PartialEq, Eq)]
|
||||
pub struct PboxArgs {
|
||||
#[clap(value_parser=maybe_hex::<u8>)]
|
||||
pub n: u8,
|
||||
}
|
||||
|
||||
#[derive(Subcommand, Clone, Debug, PartialEq, Eq)]
|
||||
pub enum AlgoActions {
|
||||
#[command(name="feistel0-i")]
|
||||
|
|
|
@ -48,7 +48,7 @@ pub fn seperator() {
|
|||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// process a result with some int
|
||||
pub fn proc_result<T, K>(result: Result<T, K>, args: Cli)
|
||||
pub fn proc_result_num<T, K>(result: Result<T, K>, args: Cli)
|
||||
where
|
||||
T: Debug,
|
||||
T: Integer,
|
||||
|
@ -60,23 +60,11 @@ pub fn proc_result<T, K>(result: Result<T, K>, args: Cli)
|
|||
seperator();
|
||||
}
|
||||
match result {
|
||||
Ok(res) => {
|
||||
if args.machine {
|
||||
println!("{} ({:#x})", res, res);
|
||||
}
|
||||
else {
|
||||
seperator();
|
||||
println!("result is {} ({:#x})", res, res);
|
||||
}
|
||||
Ok(num) => {
|
||||
proc_num(num, args);
|
||||
}
|
||||
Err(e) => {
|
||||
if args.machine {
|
||||
println!("{:#?}", e)
|
||||
}
|
||||
else {
|
||||
seperator();
|
||||
println!("could not compute:\n{:#?}", e)
|
||||
}
|
||||
proc_err(e, args);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -96,11 +84,51 @@ pub fn proc_num<T>(num: T, args: Cli)
|
|||
println!("{} ({:#x})", num, num);
|
||||
}
|
||||
else {
|
||||
seperator();
|
||||
println!("result is {} ({:#x})", num, num);
|
||||
}
|
||||
}
|
||||
|
||||
/// process some int tuple
|
||||
pub fn proc_result_tup_num<T, K>(result: Result<(T, T), K>, args: Cli)
|
||||
where
|
||||
T: Debug,
|
||||
T: Integer,
|
||||
T: LowerHex,
|
||||
T: Display,
|
||||
K: Debug
|
||||
{
|
||||
if args.verbose {
|
||||
seperator();
|
||||
}
|
||||
match result {
|
||||
Ok(tup) => {
|
||||
proc_tup_num(tup, args);
|
||||
}
|
||||
Err(e) => {
|
||||
proc_err(e, args);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// process some int tuple result
|
||||
pub fn proc_tup_num<T>(num: (T, T), args: Cli)
|
||||
where
|
||||
T: Debug,
|
||||
T: Integer,
|
||||
T: LowerHex,
|
||||
T: Display,
|
||||
{
|
||||
if args.verbose {
|
||||
seperator();
|
||||
}
|
||||
if args.machine {
|
||||
println!("({}{}) (({:#x}, {:#x})", num.0, num.1, num.0, num.1);
|
||||
}
|
||||
else {
|
||||
println!("result is ({}{}) (({:#x}, {:#x})", num.0, num.1, num.0, num.1);
|
||||
}
|
||||
}
|
||||
|
||||
/// process some vec
|
||||
pub fn proc_vec<T>(vec: Vec<T>, args: Cli)
|
||||
where
|
||||
|
@ -113,7 +141,6 @@ pub fn proc_vec<T>(vec: Vec<T>, args: Cli)
|
|||
println!("{:#?}", vec);
|
||||
}
|
||||
else {
|
||||
seperator();
|
||||
println!("result is\n{:#?}", vec);
|
||||
}
|
||||
}
|
||||
|
@ -129,22 +156,23 @@ pub fn proc_result_vec<T, K>(res: Result<Vec<T>, K>, args: Cli)
|
|||
}
|
||||
match res {
|
||||
Ok(vec) => {
|
||||
if args.machine {
|
||||
println!("{:#?}", vec);
|
||||
}
|
||||
else {
|
||||
seperator();
|
||||
println!("result is {:#?}", vec);
|
||||
}
|
||||
proc_vec(vec, args);
|
||||
}
|
||||
Err(e) => {
|
||||
proc_err(e, args);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// process some error
|
||||
pub fn proc_err<T>(e: T, args: Cli)
|
||||
where
|
||||
T: Debug
|
||||
{
|
||||
if args.machine {
|
||||
println!("{:#?}", e)
|
||||
}
|
||||
else {
|
||||
seperator();
|
||||
println!("could not compute:\n{:#?}", e)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
12
src/main.rs
12
src/main.rs
|
@ -50,7 +50,7 @@ pub fn main() {
|
|||
}
|
||||
MathActions::Modred(mod_red_args) => {
|
||||
let result = math::modred::modred(mod_red_args.polynomial, mod_red_args.relation, args.verbose);
|
||||
cplex::printing::proc_result(result, args);
|
||||
cplex::printing::proc_result_num(result, args);
|
||||
}
|
||||
MathActions::Pm1(pm1_args) => {
|
||||
let vec: Result<Vec<u128>, String> = math::pm1::p_minus_one(
|
||||
|
@ -64,8 +64,8 @@ pub fn main() {
|
|||
let field = math::gallois::GalloisFiled::new(gal_args.field, args.verbose);
|
||||
match gal_args.action {
|
||||
GalloisActions::Sqrt(gal_sqrt_args) => {
|
||||
let result = field.sqrt(gal_sqrt_args.n);
|
||||
cplex::printing::proc_result(result, args);
|
||||
let result = field.sqrt(gal_sqrt_args.a);
|
||||
cplex::printing::proc_result_tup_num(result, args);
|
||||
}
|
||||
GalloisActions::Reduce(gal_red_args) => {
|
||||
let result = field.reduce_neg(gal_red_args.n);
|
||||
|
@ -73,7 +73,7 @@ pub fn main() {
|
|||
}
|
||||
GalloisActions::Invert(gal_inv_args) => {
|
||||
let result = field.inverse(gal_inv_args.n);
|
||||
cplex::printing::proc_result(result, args);
|
||||
cplex::printing::proc_result_num(result, args);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -95,6 +95,10 @@ pub fn main() {
|
|||
let result: u128 = binary::xor(bin_xor_args.a, bin_xor_args.b);
|
||||
cplex::printing::proc_num(result, args);
|
||||
}
|
||||
BinaryActions::Pbox(pbox_args) => {
|
||||
let result: u8 = binary::pbox6::pbox6(pbox_args.n);
|
||||
cplex::printing::proc_num(result, args);
|
||||
}
|
||||
}
|
||||
}
|
||||
Commands::Algo(action) => {
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
/// License: MIT
|
||||
/// Source: <https://git.cscherr.de/PlexSheep/plexcryptool/>
|
||||
|
||||
use crate::math::modexp;
|
||||
use crate::{math::modexp, cplex::printing::seperator};
|
||||
|
||||
use core::fmt;
|
||||
|
||||
|
@ -63,7 +63,9 @@ impl GalloisFiled {
|
|||
verbose
|
||||
};
|
||||
if verbose {
|
||||
dbg!(&field);
|
||||
seperator();
|
||||
println!("In Gallois Field F_{}", field.base);
|
||||
seperator();
|
||||
}
|
||||
return field;
|
||||
}
|
||||
|
@ -101,8 +103,8 @@ impl GalloisFiled {
|
|||
return Err(NoInverseError);
|
||||
}
|
||||
let egcd = (n as i128).extended_gcd(&(self.base as i128));
|
||||
dbg!(n);
|
||||
return Ok(egcd.x as u128);
|
||||
let egcd = self.reduce(egcd.x as u128);
|
||||
return Ok(egcd);
|
||||
}
|
||||
|
||||
pub fn divide(self, a: u128, b: u128) -> Result<u128, DivisionByZeroError> {
|
||||
|
@ -119,17 +121,111 @@ impl GalloisFiled {
|
|||
}
|
||||
|
||||
/// calculate the square root of a number in a field
|
||||
pub fn sqrt(self, n: u128) -> Result<u128, NoRootError> {
|
||||
// TODO implement this
|
||||
panic!("TODO")
|
||||
pub fn sqrt(self, a: u128) -> Result<(u128, u128), NoRootError> {
|
||||
let pm1 = self.base - 1;
|
||||
let pm1_2 = pm1.checked_div(2).expect("Could not divide p-1 by 2");
|
||||
let a_pm1_2 = modexp::modular_exponentiation_wrapper(a, pm1_2, self.base, false);
|
||||
if self.verbose {
|
||||
println!("p-1 = {pm1}\n[p-1]/[2] = {pm1_2}\na**([p-1]/[2]) = {a_pm1_2}");
|
||||
}
|
||||
if a_pm1_2 != 1 {
|
||||
if self.verbose {
|
||||
println!("a**([p-1]/[2]) != 1 => a has no root.");
|
||||
}
|
||||
return Err(NoRootError);
|
||||
}
|
||||
|
||||
// 4 | (p + 1):
|
||||
if 4 % (self.base + 1) == 0 {
|
||||
let w1 = a_pm1_2;
|
||||
let w1 = self.reduce(w1);
|
||||
let w2 = self.a_inverse(w1);
|
||||
if self.verbose {
|
||||
seperator();
|
||||
println!("4 divides p+1");
|
||||
println!("found sqrt of {a} as ({w1}, {w2})");
|
||||
}
|
||||
return Ok((w1, w2));
|
||||
}
|
||||
// 4 !| (p + 1):
|
||||
else {
|
||||
if self.verbose {
|
||||
seperator();
|
||||
println!("4 does not divide p+1");
|
||||
seperator();
|
||||
}
|
||||
let mut l: u128 = 0;
|
||||
let t: u128;
|
||||
loop {
|
||||
if pm1_2.is_multiple_of(&2u128.pow((l+1) as u32)) {
|
||||
l += 1;
|
||||
}
|
||||
else {
|
||||
// no more divisible
|
||||
t = pm1_2.checked_div(2u128.pow(l as u32)).expect("Could not divide by 2**l as calculated");
|
||||
// t must be odd
|
||||
assert_eq!(t % 2, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
// chose a b so that b_pm1_2 == -1
|
||||
let mut b: Option<u128> = None;
|
||||
let mut b_pm1_2: u128;
|
||||
for b_candidate in 0..self.base {
|
||||
b_pm1_2 = modexp::modular_exponentiation_wrapper(b_candidate, pm1_2, self.base, false);
|
||||
if self.reduce(b_pm1_2) == self.reduce_neg(-1) {
|
||||
b = Some(b_candidate);
|
||||
if self.verbose {
|
||||
println!("found a b that fits the criteria: {}", b.unwrap());
|
||||
seperator();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if b.is_none() {
|
||||
if self.verbose {
|
||||
seperator();
|
||||
println!("found no fitting b");
|
||||
}
|
||||
return Err(NoRootError);
|
||||
}
|
||||
let b = b.unwrap();
|
||||
let mut n: Vec<u128> = vec![0];
|
||||
let mut c: Vec<u128> = vec![];
|
||||
let mut tmp: u128;
|
||||
for index in 0..l {
|
||||
// l-(i+1)
|
||||
tmp = l - (index+1);
|
||||
c[index as usize] = a.pow(2u32.pow((self.reduce(l as u128 - (index as u128 + 1)) * t) as u32) as u32) * b.pow(n[index as usize] as u32);
|
||||
if self.verbose {
|
||||
println!("{index}.\tc_{index} = {}", c[index as usize]);
|
||||
}
|
||||
if self.reduce(c[index as usize]) == 1 {
|
||||
n[(index + 1) as usize] = n[index as usize].checked_div(2).expect("could not compute n[i+1]");
|
||||
}
|
||||
else {
|
||||
n[(index + 1) as usize] = n[index as usize].checked_div(2).expect("could not compute n[i+1]")
|
||||
+ pm1.checked_div(4).expect("could not compute n[i+1]");
|
||||
}
|
||||
}
|
||||
let w1 = a.pow((t + 1).checked_div(2).expect("could not compute w") as u32) * b.pow(n[l as usize] as u32);
|
||||
let w1 = self.reduce(w1);
|
||||
let w2 = self.a_inverse(w1);
|
||||
if self.verbose {
|
||||
println!("found sqrt of {a} as ({w1}, {w2})");
|
||||
}
|
||||
return Ok((w1, w2));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#[test]
|
||||
fn test_gallois_sqrt() {
|
||||
let field = GalloisFiled::new(67, true);
|
||||
panic!("TODO")
|
||||
let field = GalloisFiled::new(977, false);
|
||||
assert_eq!(field.sqrt(269).expect("function says there is no root but there is"), (313, 474));
|
||||
assert_eq!(field.sqrt(524).expect("function says there is no root but there is"), (115, 862));
|
||||
assert_eq!(field.sqrt(275).expect("function says there is no root but there is"), (585, 392));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -19,6 +19,19 @@ fn test_modred() {
|
|||
let rel: u64 = 0x1053;
|
||||
let pol0: u64 = 0x100001;
|
||||
assert_eq!(modred(pol0, rel, false).unwrap(), 0x21e);
|
||||
// test vectors by our professor
|
||||
// IDK why some of these don't work, but I am pretty sure that my algorithm and implementation
|
||||
// works just fine. Maybe these are wrong?
|
||||
assert_eq!(modred(0xe8a3eb51c73156fd, 0x89e34420532421cc, false).unwrap(), 0x6140af7194157731);
|
||||
assert_eq!(modred(0x5a85ec7f1b500672, 0x2d25dc91aaab6ff4, false).unwrap(), 0xce555c4e06d99a);
|
||||
//assert_eq!(modred(0xe1dc2ce9498922c0, 0x500d9154348e2e12, false).unwrap(), 0x11ca9f15141b50f6);
|
||||
assert_eq!(modred(0xa478746c853a06ed, 0x9e099288b8afd5f0, false).unwrap(), 0x3a71e6e43d95d31d);
|
||||
assert_eq!(modred(0xd1dd497ffbf09438, 0x7fbfbaa628496279, false).unwrap(), 0x2ea23c33ab6250ca);
|
||||
//assert_eq!(modred(0xdb5ac58d690d7a5e, 0x1f9151e2fba999ec, false).unwrap(), 0x763b8bdb8bb1f0a);
|
||||
assert_eq!(modred(0xfb4c381f1a65e7eb, 0xd5c0b4b71112728e, false).unwrap(), 0x2e8c8ca80b779565);
|
||||
assert_eq!(modred(0x87651817df45df82, 0x42ecbd7a63618cf3, false).unwrap(), 0x2bc62e31986c664);
|
||||
assert_eq!(modred(0x79a5e837d0b4c33e, 0x11f, false).unwrap(), 0xe2);
|
||||
assert_eq!(modred(0xd442873e9eb2de0e, 0x341, false).unwrap(), 0xcd);
|
||||
}
|
||||
|
||||
/// modular reduction of a polynomial with a given relation
|
||||
|
|
Loading…
Reference in New Issue