oaep rsa base
This commit is contained in:
parent
6460e939e8
commit
7bcd404185
|
@ -0,0 +1,92 @@
|
|||
#!/usr/bin/env python3
|
||||
"""
|
||||
Perform RSA-OAEP
|
||||
|
||||
@author: Christoph J. Scherr <software@cscherr.de>
|
||||
@license: MIT
|
||||
@source: https://git.cscherr.de/PlexSheep/plexcryptool/src/branch/master/plexcryptool/trash-hash.py
|
||||
"""
|
||||
|
||||
import hashlib
|
||||
from math import floor
|
||||
|
||||
# the given key in the assignment
|
||||
GIVEN_PUB_KEY = (0xAF5466C26A6B662AC98C06023501C9DF6036B065BD1F6804B1FC86307718DA4048211FD68A06917DE6F81DC018DCAF84B38AB77A6538BA2FE6664D3FB81E4A0886BBCDAB071AD6823FE20DF1CD67D33FB6CC5DA519F69B11F3D48534074A83F03A5A9545427720A30A27432E94970155A026572E358072023061AF65A2A18E85, 0x10001)
|
||||
|
||||
SEED_LENGTH = 8 # bytes
|
||||
|
||||
def mgf1(seed: bytearray, length: int, hash_func=hashlib.sha256) -> bytearray:
|
||||
"""
|
||||
Code stolen from wikipedia
|
||||
"""
|
||||
hLen = hash_func().digest_size
|
||||
# https://www.ietf.org/rfc/rfc2437.txt
|
||||
# 1.If l > 2^32(hLen), output "mask too long" and stop.
|
||||
if length > (hLen << 32):
|
||||
raise ValueError("mask too long")
|
||||
# 2.Let T be the empty octet string.
|
||||
T = b""
|
||||
# 3.For counter from 0 to \lceil{l / hLen}\rceil-1, do the following:
|
||||
# Note: \lceil{l / hLen}\rceil-1 is the number of iterations needed,
|
||||
# but it's easier to check if we have reached the desired length.
|
||||
counter = 0
|
||||
while len(T) < length:
|
||||
# a.Convert counter to an octet string C of length 4 with the primitive I2OSP: C = I2OSP (counter, 4)
|
||||
C = int.to_bytes(counter, 4, 'big')
|
||||
# b.Concatenate the hash of the seed Z and C to the octet string T: T = T || Hash (Z || C)
|
||||
T += hash_func(seed + C).digest()
|
||||
counter += 1
|
||||
# 4.Output the leading l octets of T as the octet string mask.
|
||||
return bytearray(T[:length])
|
||||
|
||||
def byte_xor(ba1: bytearray, ba2: bytearray):
|
||||
a = int(ba1.hex(), 16)
|
||||
b = int(ba2.hex(), 16)
|
||||
c = a^b
|
||||
if c.bit_length() / 8 == floor(c.bit_length() / 8):
|
||||
clen = floor(c.bit_length() / 8)
|
||||
else:
|
||||
clen = floor(c.bit_length() / 8) + 1
|
||||
return bytearray(c.to_bytes(clen, 'big'))
|
||||
|
||||
|
||||
def rsa_oaep_inner(seed: bytearray, datablock: bytearray) -> tuple[bytearray, bytearray, bytearray]:
|
||||
mgf_seed = mgf1(seed, len(seed))
|
||||
masked_db = byte_xor(mgf_seed, datablock)
|
||||
print(masked_db.hex())
|
||||
|
||||
def test_rsa_oaep_inner():
|
||||
seed: bytearray = bytearray.fromhex("aa1122fe0815beef")
|
||||
db: bytearray = bytearray.fromhex("""
|
||||
00000000000000000000000000000000000000000000000000000000
|
||||
00000000000000000000000000000000000000000000000000000000
|
||||
00000000000000000000000000000000000000000000000000000000
|
||||
00000000000000000000000000000000000001466f6f626172203132
|
||||
33343536373839
|
||||
""")
|
||||
print("seed\t%s" % seed.hex())
|
||||
print("db\t%s" % db.hex())
|
||||
|
||||
result = rsa_oaep_inner(seed, db)
|
||||
|
||||
GIVEN_MASK_FOR_DB = bytearray.fromhex("""
|
||||
ea600669f6f16b3a2ad05d4b6d9b23911c8cc432fddd8d34a68d88af
|
||||
3d787b7eebf6cd1b720812086758ce56e24ab819ccd8fb5eedb1cae9
|
||||
f6f895667d7f89d0454b828777ecabc040a649c8956e78ec1c721370
|
||||
663065cbc343deabad9eb6f2aceab6bfed5beb232cc55413bfffa06e
|
||||
68627d7ec3ded5
|
||||
""")
|
||||
GIVEN_MASKED_DB = bytearray.fromhex("""
|
||||
ea600669f6f16b3a2ad05d4b6d9b23911c8cc432fddd8d34a68d88af
|
||||
3d787b7eebf6cd1b720812086758ce56e24ab819ccd8fb5eedb1cae9
|
||||
f6f895667d7f89d0454b828777ecabc040a649c8956e78ec1c721370
|
||||
663065cbc343deabad9eb6f2aceab6bfed5bea6543aa3672cddf915c
|
||||
5b564848f4e6ec
|
||||
""")
|
||||
GIVEN_MASK_FOR_SEED = bytearray.fromhex("713162084a4e0e6d ")
|
||||
GIVEN_MASKED_SEED = bytearray.fromhex("db2040f6425bb082")
|
||||
assert result[0] == GIVEN_MASKED_SEED, "is %s" % result[0].hex()
|
||||
assert result[1] == GIVEN_MASKED_DB, "is %s" % result[1].hex()
|
||||
|
||||
if __name__ == "__main__":
|
||||
test_rsa_oaep_inner()
|
|
@ -68,7 +68,7 @@ impl ElipticCurve {
|
|||
|
||||
#[test]
|
||||
fn test_check_point() {
|
||||
let f = GalloisField::new(1151, true);
|
||||
let f = GalloisField::new(1151, true, None);
|
||||
let ec = ElipticCurve::new(f, 1, 679, true);
|
||||
// real points
|
||||
let p = vec![
|
||||
|
|
|
@ -25,6 +25,12 @@ use pyo3::{prelude::*, exceptions::PyValueError};
|
|||
|
||||
use primes::is_prime;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
pub const F_8_DEFAULT_RELATION: u128 = 0xb;
|
||||
pub const F_16_DEFAULT_RELATION: u128 = 0x13;
|
||||
pub const F_256_DEFAULT_RELATION: u128 = 0x11b;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#[derive(Debug)]
|
||||
/// used when trying to find a root for a number which does not have a root.
|
||||
|
@ -70,11 +76,28 @@ pub struct GalloisField {
|
|||
/// implementations for the gallois field
|
||||
impl GalloisField {
|
||||
/// make a new gallois field
|
||||
pub fn new(base: u128, verbose: bool, relation: Option<u128>) -> Self {
|
||||
pub fn new(base: u128, verbose: bool, mut relation: Option<u128>) -> Self {
|
||||
let prime_base: bool = is_prime(base as u64);
|
||||
if !prime_base {
|
||||
println!("Non prime bases for a field are currently very experimental.\n
|
||||
Use them at your own risk! ({} is not a prime.)", base);
|
||||
println!("Non prime bases for a field are currently very experimental.\nUse them at your own risk! ({} is not a prime.)", base);
|
||||
if relation.is_none() {
|
||||
// TODO choose common relations for known fields
|
||||
|
||||
match base {
|
||||
8 => {
|
||||
relation = Some(F_8_DEFAULT_RELATION);
|
||||
}
|
||||
16 => {
|
||||
relation = Some(F_16_DEFAULT_RELATION);
|
||||
}
|
||||
256 => {
|
||||
relation = Some(F_256_DEFAULT_RELATION);
|
||||
}
|
||||
_ => {
|
||||
panic!("You did not specify a relation and none could be found.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
let mut field = GalloisField{
|
||||
base,
|
||||
|
@ -124,7 +147,7 @@ impl GalloisField {
|
|||
if n < 0 {
|
||||
panic!("reduction for negative numbers not implemented.");
|
||||
}
|
||||
modred(n as u128, self.relation.unwrap(), self.verbose).expect("modular reduction didn't work")
|
||||
modred(n as u128, self.relation.unwrap(), false).expect("modular reduction didn't work")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -421,6 +444,16 @@ fn test_gallois_sqrt() {
|
|||
assert_eq!(field.sqrt(275).expect("function says there is no root but there is"), (585, 392));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_gallois_reduce() {
|
||||
let field = GalloisField::new(977, true, None);
|
||||
for i in 0..976 {
|
||||
assert_eq!(field.reduce(i), i);
|
||||
}
|
||||
|
||||
let field = GalloisField::new(16, true, None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_gallois_inverse() {
|
||||
let field = GalloisField::new(31, true, None);
|
||||
|
@ -438,10 +471,10 @@ fn test_gallois_inverse() {
|
|||
assert_eq!(field.inverse(7).unwrap(), 10);
|
||||
assert!(field.inverse(0).is_err());
|
||||
|
||||
// TODO i think this test does not catch all edge cases. In some cases, something seems to be
|
||||
// wrong.
|
||||
|
||||
// TODO add a test for a field that has a non prime base
|
||||
let field = GalloisField::new(16, true, None);
|
||||
assert_eq!(field.inverse(0x130).unwrap(), 0);
|
||||
assert!(field.inverse(0).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -450,8 +483,8 @@ fn test_calc_char() {
|
|||
assert_eq!(GalloisField::new(1151, true, None).calc_char(), 1151);
|
||||
assert_eq!(GalloisField::new(2, true, None).calc_char(), 2);
|
||||
|
||||
// only primes are supported right now. TODO
|
||||
//assert_eq!(GalloisField::new(8, true).calc_char(), 2);
|
||||
//assert_eq!(GalloisField::new(64, true).calc_char(), 2);
|
||||
//assert_eq!(GalloisField::new(2u128.pow(64u32), true).calc_char(), 2);
|
||||
// experimental
|
||||
assert_eq!(GalloisField::new(8, true, None).calc_char(), 2);
|
||||
assert_eq!(GalloisField::new(64, true, None).calc_char(), 2);
|
||||
//assert_eq!(GalloisField::new(2u128.pow(64u32), true, None).calc_char(), 2);
|
||||
}
|
||||
|
|
|
@ -159,5 +159,4 @@ fn dump_bin(bytes: &Vec<u8>) {
|
|||
print!("{:08b}", byte);
|
||||
}
|
||||
println!();
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue