Compare commits

..

No commits in common. "b9067599d409c569990efa97a5dfb6bd0bdd27ca" and "8dc063e4e5ab551a6e4304dd610da48a31175558" have entirely different histories.

11 changed files with 236 additions and 630 deletions

270
Cargo.lock generated
View file

@ -57,18 +57,6 @@ version = "1.0.71"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8" checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8"
[[package]]
name = "autocfg"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "base16ct"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf"
[[package]] [[package]]
name = "bitflags" name = "bitflags"
version = "1.3.2" version = "1.3.2"
@ -84,15 +72,6 @@ dependencies = [
"cfg-if", "cfg-if",
] ]
[[package]]
name = "block-buffer"
version = "0.10.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
dependencies = [
"generic-array",
]
[[package]] [[package]]
name = "cc" name = "cc"
version = "1.0.79" version = "1.0.79"
@ -153,63 +132,6 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
[[package]]
name = "cpufeatures"
version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "03e69e28e9f7f77debdedbaafa2866e1de9ba56df55a8bd7cfc724c25a09987c"
dependencies = [
"libc",
]
[[package]]
name = "crypto-bigint"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf4c2f4e1afd912bc40bfd6fed5d9dc1f288e0ba01bfcc835cc5bc3eb13efe15"
dependencies = [
"generic-array",
"rand_core",
"subtle",
"zeroize",
]
[[package]]
name = "crypto-common"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
dependencies = [
"generic-array",
"typenum",
]
[[package]]
name = "digest"
version = "0.10.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
dependencies = [
"block-buffer",
"crypto-common",
]
[[package]]
name = "elliptic-curve"
version = "0.13.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "968405c8fdc9b3bf4df0a6638858cc0b52462836ab6b1c87377785dd09cf1c0b"
dependencies = [
"base16ct",
"crypto-bigint",
"ff",
"generic-array",
"group",
"rand_core",
"subtle",
"zeroize",
]
[[package]] [[package]]
name = "errno" name = "errno"
version = "0.3.1" version = "0.3.1"
@ -232,47 +154,19 @@ dependencies = [
] ]
[[package]] [[package]]
name = "ff" name = "foreign-types"
version = "0.13.0" version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
dependencies = [ dependencies = [
"rand_core", "foreign-types-shared",
"subtle",
] ]
[[package]] [[package]]
name = "generic-array" name = "foreign-types-shared"
version = "0.14.7" version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
dependencies = [
"typenum",
"version_check",
"zeroize",
]
[[package]]
name = "getrandom"
version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427"
dependencies = [
"cfg-if",
"libc",
"wasi",
]
[[package]]
name = "group"
version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63"
dependencies = [
"ff",
"rand_core",
"subtle",
]
[[package]] [[package]]
name = "heck" name = "heck"
@ -333,37 +227,6 @@ version = "0.4.19"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4"
[[package]]
name = "num-bigint"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f93ab6289c7b344a8a9f60f88d80aa20032336fe78da341afc91c8a2341fc75f"
dependencies = [
"autocfg",
"num-integer",
"num-traits",
"rand",
]
[[package]]
name = "num-integer"
version = "0.1.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9"
dependencies = [
"autocfg",
"num-traits",
]
[[package]]
name = "num-traits"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd"
dependencies = [
"autocfg",
]
[[package]] [[package]]
name = "once_cell" name = "once_cell"
version = "1.18.0" version = "1.18.0"
@ -371,10 +234,45 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
[[package]] [[package]]
name = "ppv-lite86" name = "openssl"
version = "0.2.17" version = "0.10.55"
source = "git+https://github.com/sfackler/rust-openssl#9d180ec94a92d2d08d6463ad047d9d7e7a8d9561"
dependencies = [
"bitflags",
"cfg-if",
"foreign-types",
"libc",
"once_cell",
"openssl-macros",
"openssl-sys",
]
[[package]]
name = "openssl-macros"
version = "0.1.1"
source = "git+https://github.com/sfackler/rust-openssl#9d180ec94a92d2d08d6463ad047d9d7e7a8d9561"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "openssl-sys"
version = "0.9.90"
source = "git+https://github.com/sfackler/rust-openssl#9d180ec94a92d2d08d6463ad047d9d7e7a8d9561"
dependencies = [
"cc",
"libc",
"pkg-config",
"vcpkg",
]
[[package]]
name = "pkg-config"
version = "0.3.27"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964"
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro2"
@ -394,36 +292,6 @@ dependencies = [
"proc-macro2", "proc-macro2",
] ]
[[package]]
name = "rand"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
dependencies = [
"libc",
"rand_chacha",
"rand_core",
]
[[package]]
name = "rand_chacha"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
dependencies = [
"ppv-lite86",
"rand_core",
]
[[package]]
name = "rand_core"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
dependencies = [
"getrandom",
]
[[package]] [[package]]
name = "rustix" name = "rustix"
version = "0.37.20" version = "0.37.20"
@ -475,17 +343,6 @@ dependencies = [
"serde", "serde",
] ]
[[package]]
name = "sha1"
version = "0.10.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3"
dependencies = [
"cfg-if",
"cpufeatures",
"digest",
]
[[package]] [[package]]
name = "simple_logger" name = "simple_logger"
version = "4.2.0" version = "4.2.0"
@ -502,12 +359,6 @@ version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]]
name = "subtle"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc"
[[package]] [[package]]
name = "syn" name = "syn"
version = "2.0.21" version = "2.0.21"
@ -539,25 +390,14 @@ dependencies = [
"syn", "syn",
] ]
[[package]]
name = "typenum"
version = "1.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba"
[[package]] [[package]]
name = "umskt" name = "umskt"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"bitreader", "bitreader",
"elliptic-curve", "openssl",
"num-bigint",
"num-integer",
"num-traits",
"rand",
"serde_json", "serde_json",
"sha1",
"thiserror", "thiserror",
] ]
@ -574,16 +414,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
[[package]] [[package]]
name = "version_check" name = "vcpkg"
version = "0.9.4" version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
[[package]]
name = "wasi"
version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]] [[package]]
name = "windows-sys" name = "windows-sys"
@ -720,9 +554,3 @@ dependencies = [
"simple_logger", "simple_logger",
"umskt", "umskt",
] ]
[[package]]
name = "zeroize"
version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9"

View file

@ -1,5 +1,4 @@
[workspace] [workspace]
resolver = "2"
members = [ members = [
"umskt", "umskt",

View file

@ -6,12 +6,7 @@ edition = "2021"
[dependencies] [dependencies]
anyhow = "1.0.71" anyhow = "1.0.71"
bitreader = "0.3.7" bitreader = "0.3.7"
elliptic-curve = "0.13.5" openssl = { git = "https://github.com/sfackler/rust-openssl" }
num-bigint = { version = "0.4.3", features = ["rand"] }
num-integer = "0.1.45"
num-traits = "0.2.15"
rand = "0.8.5"
sha1 = "0.10.5"
thiserror = "1.0.40" thiserror = "1.0.40"
[dev-dependencies] [dev-dependencies]

View file

@ -1,24 +1,20 @@
use std::{ use std::fmt::{Display, Formatter};
cmp::Ordering,
fmt::{Display, Formatter},
};
use anyhow::{bail, Result}; use anyhow::{bail, Result};
use bitreader::BitReader; use bitreader::BitReader;
use num_bigint::{BigInt, BigUint, RandomBits}; use openssl::{
use num_integer::Integer; bn::{BigNum, BigNumContext, MsbOption},
use num_traits::{FromPrimitive, ToPrimitive}; ec::{EcGroup, EcPoint},
use rand::Rng; sha::sha1,
use sha1::{Digest, Sha1}; };
use crate::{ use crate::{
crypto::{EllipticCurve, PrivateKey}, crypto::{EllipticCurve, PrivateKey},
key::{base24_decode, base24_encode, strip_key}, key::{base24_decode, base24_encode, strip_key},
math::bitmask, math::bitmask,
weierstrass_curve::{Point, WeierstrassCurve},
}; };
const FIELD_BITS: u64 = 384; const FIELD_BITS: i32 = 384;
const FIELD_BYTES: usize = 48; const FIELD_BYTES: usize = 48;
const SHA_MSG_LENGTH: usize = 4 + 2 * FIELD_BYTES; const SHA_MSG_LENGTH: usize = 4 + 2 * FIELD_BYTES;
@ -48,24 +44,22 @@ impl ProductKey {
let sequence = match sequence { let sequence = match sequence {
Some(serial) => serial, Some(serial) => serial,
None => { None => {
let mut rng = rand::thread_rng(); let mut bn_rand = BigNum::new()?;
let random: BigInt = rng.sample(RandomBits::new(32)); bn_rand.rand(19, MsbOption::MAYBE_ZERO, false)?;
let raw = u32::from_be_bytes(random.to_bytes_be().1[0..4].try_into().unwrap()); let o_raw = u32::from_be_bytes(bn_rand.to_vec_padded(4)?.try_into().unwrap());
raw % 999999 o_raw % 999999
} }
}; };
// Default to upgrade=false // Default to upgrade=false
let upgrade = upgrade.unwrap_or(false); let upgrade = upgrade.unwrap_or(false);
let private = &private_key.gen_order - &private_key.private_key;
// Generate a new random key // Generate a new random key
let product_key = Self::generate( let product_key = Self::generate(
&curve.curve, &curve.curve,
&curve.gen_point, &curve.gen_point,
&private_key.gen_order, &private_key.gen_order,
&private, &private_key.private_key,
channel_id, channel_id,
sequence, sequence,
upgrade, upgrade,
@ -89,75 +83,62 @@ impl ProductKey {
} }
fn generate( fn generate(
e_curve: &WeierstrassCurve, e_curve: &EcGroup,
base_point: &Point, base_point: &EcPoint,
gen_order: &BigInt, gen_order: &BigNum,
private_key: &BigInt, private_key: &BigNum,
channel_id: u32, channel_id: u32,
sequence: u32, sequence: u32,
upgrade: bool, upgrade: bool,
) -> Result<Self> { ) -> Result<Self> {
let mut num_context = BigNumContext::new().unwrap();
let mut c = BigNum::new()?;
let mut s = BigNum::new()?;
let mut x = BigNum::new()?;
let mut y = BigNum::new()?;
let mut ek: BigNum;
let serial = channel_id * 1_000_000 + sequence; let serial = channel_id * 1_000_000 + sequence;
let data = serial << 1 | upgrade as u32; let data = serial << 1 | upgrade as u32;
let mut rng = rand::thread_rng();
let product_key = loop { let product_key = loop {
let mut r = EcPoint::new(e_curve)?;
// Generate a random number c consisting of 384 bits without any constraints. // Generate a random number c consisting of 384 bits without any constraints.
let c: BigUint = rng.sample(RandomBits::new(FIELD_BITS)); c.rand(FIELD_BITS, MsbOption::MAYBE_ZERO, false)?;
let c: BigInt = c.into();
// Pick a random derivative of the base point on the elliptic curve. // Pick a random derivative of the base point on the elliptic curve.
// R = cG; // R = cG;
let r = e_curve.multiply_point(&c, base_point); r.mul(e_curve, base_point, &c, &num_context)?;
// Acquire its coordinates. // Acquire its coordinates.
// x = R.x; y = R.y; // x = R.x; y = R.y;
let (x, y) = match r { r.affine_coordinates(e_curve, &mut x, &mut y, &mut num_context)?;
Point::Point { x, y } => (x, y),
Point::Infinity => bail!("Point at infinity!"),
};
let mut msg_buffer: [u8; SHA_MSG_LENGTH] = [0; SHA_MSG_LENGTH]; let mut msg_buffer: [u8; SHA_MSG_LENGTH] = [0; SHA_MSG_LENGTH];
let x_bin = x.to_bytes_le().1; let mut x_bin = x.to_vec_padded(FIELD_BYTES as i32)?;
let x_bin = match x_bin.len().cmp(&FIELD_BYTES) { x_bin.reverse();
Ordering::Less => (0..FIELD_BYTES - x_bin.len()) let mut y_bin = y.to_vec_padded(FIELD_BYTES as i32)?;
.map(|_| 0) y_bin.reverse();
.chain(x_bin.into_iter())
.collect(),
Ordering::Greater => continue,
Ordering::Equal => x_bin,
};
let y_bin = y.to_bytes_le().1;
let y_bin = match y_bin.len().cmp(&FIELD_BYTES) {
Ordering::Less => (0..FIELD_BYTES - y_bin.len())
.map(|_| 0)
.chain(y_bin.into_iter())
.collect(),
Ordering::Greater => continue,
Ordering::Equal => y_bin,
};
msg_buffer[0..4].copy_from_slice(&data.to_le_bytes()); msg_buffer[0..4].copy_from_slice(&data.to_le_bytes());
msg_buffer[4..4 + FIELD_BYTES].copy_from_slice(&x_bin); msg_buffer[4..4 + FIELD_BYTES].copy_from_slice(&x_bin);
msg_buffer[4 + FIELD_BYTES..4 + FIELD_BYTES * 2].copy_from_slice(&y_bin); msg_buffer[4 + FIELD_BYTES..4 + FIELD_BYTES * 2].copy_from_slice(&y_bin);
let msg_digest = { let msg_digest = sha1(&msg_buffer);
let mut hasher = Sha1::new();
hasher.update(msg_buffer);
hasher.finalize()
};
let hash: u32 = let hash: u32 =
u32::from_le_bytes(msg_digest[0..4].try_into().unwrap()) >> 4 & bitmask(28) as u32; u32::from_le_bytes(msg_digest[0..4].try_into().unwrap()) >> 4 & bitmask(28) as u32;
let mut ek = private_key.clone(); ek = (*private_key).to_owned()?;
ek *= hash; ek.mul_word(hash)?;
let s = (ek + c).mod_floor(gen_order); s.mod_add(&ek, &c, gen_order, &mut num_context)?;
let signature = s.to_u64().unwrap_or(0); let signature = u64::from_be_bytes(s.to_vec_padded(8)?.try_into().unwrap());
if signature <= bitmask(55) { if signature <= bitmask(55) {
break Self { break Self {
@ -175,43 +156,36 @@ impl ProductKey {
fn verify( fn verify(
&self, &self,
e_curve: &WeierstrassCurve, e_curve: &EcGroup,
base_point: &Point, base_point: &EcPoint,
public_key: &Point, public_key: &EcPoint,
) -> Result<bool> { ) -> Result<bool> {
let e = BigInt::from_u32(self.hash).unwrap(); let mut ctx = BigNumContext::new()?;
let s = BigInt::from_u64(self.signature).unwrap();
let t = e_curve.multiply_point(&s, base_point); let e = BigNum::from_u32(self.hash)?;
let mut p = e_curve.multiply_point(&e, public_key); let s = BigNum::from_slice(&self.signature.to_be_bytes())?;
let mut x = BigNum::new()?;
let mut y = BigNum::new()?;
p = e_curve.add_points(&p, &t); let mut t = EcPoint::new(e_curve)?;
let mut p = EcPoint::new(e_curve)?;
let (x, y) = match p { t.mul(e_curve, base_point, &s, &ctx)?;
Point::Point { x, y } => (x, y), p.mul(e_curve, public_key, &e, &ctx)?;
Point::Infinity => bail!("Point at infinity!"),
}; {
let p_copy = p.to_owned(e_curve)?;
p.add(e_curve, &t, &p_copy, &mut ctx)?;
}
p.affine_coordinates(e_curve, &mut x, &mut y, &mut ctx)?;
let mut msg_buffer: [u8; SHA_MSG_LENGTH] = [0; SHA_MSG_LENGTH]; let mut msg_buffer: [u8; SHA_MSG_LENGTH] = [0; SHA_MSG_LENGTH];
let x_bin = x.to_bytes_le().1; let mut x_bin = x.to_vec_padded(FIELD_BYTES as i32)?;
let x_bin = if x_bin.len() < FIELD_BYTES { x_bin.reverse();
(0..FIELD_BYTES - x_bin.len()) let mut y_bin = y.to_vec_padded(FIELD_BYTES as i32)?;
.map(|_| 0) y_bin.reverse();
.chain(x_bin.into_iter())
.collect()
} else {
x_bin
};
let y_bin = y.to_bytes_le().1;
let y_bin = if y_bin.len() < FIELD_BYTES {
(0..FIELD_BYTES - y_bin.len())
.map(|_| 0)
.chain(y_bin.into_iter())
.collect()
} else {
y_bin
};
let serial = self.channel_id * 1_000_000 + self.sequence; let serial = self.channel_id * 1_000_000 + self.sequence;
let data = serial << 1 | self.upgrade as u32; let data = serial << 1 | self.upgrade as u32;
@ -220,11 +194,7 @@ impl ProductKey {
msg_buffer[4..4 + FIELD_BYTES].copy_from_slice(&x_bin); msg_buffer[4..4 + FIELD_BYTES].copy_from_slice(&x_bin);
msg_buffer[4 + FIELD_BYTES..4 + FIELD_BYTES * 2].copy_from_slice(&y_bin); msg_buffer[4 + FIELD_BYTES..4 + FIELD_BYTES * 2].copy_from_slice(&y_bin);
let msg_digest = { let msg_digest = sha1(&msg_buffer);
let mut hasher = Sha1::new();
hasher.update(msg_buffer);
hasher.finalize()
};
let hash: u32 = let hash: u32 =
u32::from_le_bytes(msg_digest[0..4].try_into().unwrap()) >> 4 & bitmask(28) as u32; u32::from_le_bytes(msg_digest[0..4].try_into().unwrap()) >> 4 & bitmask(28) as u32;
@ -295,7 +265,7 @@ mod tests {
use serde_json::from_reader; use serde_json::from_reader;
use crate::{bink1998, crypto::EllipticCurve}; use crate::crypto::EllipticCurve;
#[test] #[test]
fn verify_test() { fn verify_test() {
@ -313,15 +283,16 @@ mod tests {
let p = bink["p"].as_str().unwrap(); let p = bink["p"].as_str().unwrap();
let a = bink["a"].as_str().unwrap(); let a = bink["a"].as_str().unwrap();
let b = bink["b"].as_str().unwrap();
let gx = bink["g"]["x"].as_str().unwrap(); let gx = bink["g"]["x"].as_str().unwrap();
let gy = bink["g"]["y"].as_str().unwrap(); let gy = bink["g"]["y"].as_str().unwrap();
let kx = bink["pub"]["x"].as_str().unwrap(); let kx = bink["pub"]["x"].as_str().unwrap();
let ky = bink["pub"]["y"].as_str().unwrap(); let ky = bink["pub"]["y"].as_str().unwrap();
let curve = EllipticCurve::new(p, a, gx, gy, kx, ky).unwrap(); let curve = EllipticCurve::new(p, a, b, gx, gy, kx, ky).unwrap();
assert!(bink1998::ProductKey::from_key(&curve, product_key).is_ok()); assert!(super::ProductKey::from_key(&curve, product_key).is_ok());
assert!(bink1998::ProductKey::from_key(&curve, "11111-R6BG2-39J83-RYKHF-W47TT").is_err()); assert!(super::ProductKey::from_key(&curve, "11111-R6BG2-39J83-RYKHF-W47TT").is_err());
} }
#[test] #[test]

View file

@ -1,25 +1,21 @@
use std::{ use std::fmt::{Display, Formatter};
cmp::Ordering,
fmt::{Display, Formatter},
};
use anyhow::{bail, Result}; use anyhow::{bail, Result};
use bitreader::BitReader; use bitreader::BitReader;
use num_bigint::{BigInt, BigUint, RandomBits}; use openssl::{
use num_integer::Integer; bn::{BigNum, BigNumContext, MsbOption},
use num_traits::ToPrimitive; ec::{EcGroup, EcPoint},
use rand::Rng; rand::rand_bytes,
use sha1::{Digest, Sha1}; sha::sha1,
};
use crate::{ use crate::{
crypto::{EllipticCurve, PrivateKey}, crypto::{EllipticCurve, PrivateKey},
key::{base24_decode, base24_encode, strip_key}, key::{base24_decode, base24_encode, strip_key},
math::{bitmask, by_dword, next_sn_bits}, math::{bitmask, by_dword, next_sn_bits},
msr::mod_sqrt,
weierstrass_curve::{Point, WeierstrassCurve},
}; };
const FIELD_BITS: u64 = 512; const FIELD_BITS: i32 = 512;
const FIELD_BYTES: usize = 64; const FIELD_BYTES: usize = 64;
const SHA_MSG_LENGTH: usize = 3 + 2 * FIELD_BYTES; const SHA_MSG_LENGTH: usize = 3 + 2 * FIELD_BYTES;
@ -51,10 +47,9 @@ impl ProductKey {
let auth_info = match auth_info { let auth_info = match auth_info {
Some(auth_info) => auth_info, Some(auth_info) => auth_info,
None => { None => {
let mut rng = rand::thread_rng(); let mut auth_info_bytes = [0_u8; 4];
let random: BigInt = rng.sample(RandomBits::new(32)); rand_bytes(&mut auth_info_bytes)?;
let raw = u32::from_be_bytes(random.to_bytes_be().1[0..4].try_into().unwrap()); u32::from_ne_bytes(auth_info_bytes) & ((1 << 10) - 1)
raw % (bitmask(10) as u32)
} }
}; };
@ -93,50 +88,38 @@ impl ProductKey {
} }
fn generate( fn generate(
e_curve: &WeierstrassCurve, e_curve: &EcGroup,
base_point: &Point, base_point: &EcPoint,
gen_order: &BigInt, gen_order: &BigNum,
private_key: &BigInt, private_key: &BigNum,
channel_id: u32, channel_id: u32,
auth_info: u32, auth_info: u32,
upgrade: bool, upgrade: bool,
) -> Result<Self> { ) -> Result<Self> {
let data = channel_id << 1 | upgrade as u32; let mut num_context = BigNumContext::new().unwrap();
let mut rng = rand::thread_rng(); let mut c = BigNum::new()?;
let mut x = BigNum::new()?;
let mut y = BigNum::new()?;
let data = channel_id << 1 | upgrade as u32;
let mut no_square = false; let mut no_square = false;
let key = loop { let key = loop {
let c: BigUint = rng.sample(RandomBits::new(FIELD_BITS)); let mut r = EcPoint::new(e_curve)?;
let mut c: BigInt = c.into();
let r = e_curve.multiply_point(&c, base_point); c.rand(FIELD_BITS, MsbOption::MAYBE_ZERO, false)?;
let (x, y) = match r { r.mul(e_curve, base_point, &c, &num_context)?;
Point::Point { x, y } => (x, y),
Point::Infinity => bail!("Point at infinity!"), r.affine_coordinates(e_curve, &mut x, &mut y, &mut num_context)?;
};
let mut msg_buffer: [u8; SHA_MSG_LENGTH] = [0; SHA_MSG_LENGTH]; let mut msg_buffer: [u8; SHA_MSG_LENGTH] = [0; SHA_MSG_LENGTH];
let x_bin = x.to_bytes_le().1; let mut x_bin = x.to_vec_padded(FIELD_BYTES as i32)?;
let x_bin = match x_bin.len().cmp(&FIELD_BYTES) { x_bin.reverse();
Ordering::Less => (0..FIELD_BYTES - x_bin.len()) let mut y_bin = y.to_vec_padded(FIELD_BYTES as i32)?;
.map(|_| 0) y_bin.reverse();
.chain(x_bin.into_iter())
.collect(),
Ordering::Greater => continue,
Ordering::Equal => x_bin,
};
let y_bin = y.to_bytes_le().1;
let y_bin = match y_bin.len().cmp(&FIELD_BYTES) {
Ordering::Less => (0..FIELD_BYTES - y_bin.len())
.map(|_| 0)
.chain(y_bin.into_iter())
.collect(),
Ordering::Greater => continue,
Ordering::Equal => y_bin,
};
msg_buffer[0x00] = 0x79; msg_buffer[0x00] = 0x79;
msg_buffer[0x01] = (data & 0x00FF) as u8; msg_buffer[0x01] = (data & 0x00FF) as u8;
@ -145,11 +128,7 @@ impl ProductKey {
msg_buffer[3..3 + FIELD_BYTES].copy_from_slice(&x_bin); msg_buffer[3..3 + FIELD_BYTES].copy_from_slice(&x_bin);
msg_buffer[3 + FIELD_BYTES..3 + FIELD_BYTES * 2].copy_from_slice(&y_bin); msg_buffer[3 + FIELD_BYTES..3 + FIELD_BYTES * 2].copy_from_slice(&y_bin);
let msg_digest = { let msg_digest = sha1(&msg_buffer);
let mut hasher = Sha1::new();
hasher.update(msg_buffer);
hasher.finalize()
};
let hash: u32 = by_dword(&msg_digest[0..4]) & bitmask(31) as u32; let hash: u32 = by_dword(&msg_digest[0..4]) & bitmask(31) as u32;
@ -165,43 +144,42 @@ impl ProductKey {
msg_buffer[0x09] = 0x00; msg_buffer[0x09] = 0x00;
msg_buffer[0x0A] = 0x00; msg_buffer[0x0A] = 0x00;
let msg_digest = { let msg_digest = sha1(&msg_buffer[..=0x0A]);
let mut hasher = Sha1::new();
hasher.update(&msg_buffer[..=0x0A]);
hasher.finalize()
};
let i_signature = next_sn_bits(by_dword(&msg_digest[4..8]) as u64, 30, 2) << 32 let i_signature = next_sn_bits(by_dword(&msg_digest[4..8]) as u64, 30, 2) << 32
| by_dword(&msg_digest[0..4]) as u64; | by_dword(&msg_digest[0..4]) as u64;
let mut e = BigInt::from(i_signature); let mut e = BigNum::from_slice(&i_signature.to_be_bytes())?;
e = (e * private_key).mod_floor(gen_order); let e_2 = e.to_owned()?;
e.mod_mul(&e_2, private_key, gen_order, &mut num_context)?;
let mut s = e.clone(); let mut s = e.to_owned()?;
s = (&s * &s).mod_floor(gen_order); let s_2 = s.to_owned()?;
s.mod_sqr(&s_2, gen_order, &mut num_context)?;
c <<= 2; let c_2 = c.to_owned()?;
c.lshift(&c_2, 2)?;
s = &s + &c; s = &s + &c;
match mod_sqrt(&s, gen_order) { let s_2 = s.to_owned()?;
Some(res) => s = res, if s.mod_sqrt(&s_2, gen_order, &mut num_context).is_err() {
None => {
no_square = true; no_square = true;
} };
}
s = (s - e).mod_floor(gen_order); let s_2 = s.to_owned()?;
s.mod_sub(&s_2, &e, gen_order, &mut num_context)?;
if s.is_odd() { if s.is_bit_set(0) {
s = &s + gen_order; s = &s + gen_order;
} }
s >>= 1; let s_2 = s.to_owned()?;
s.rshift1(&s_2)?;
let signature = s.to_u64().unwrap_or(0); let signature = u64::from_be_bytes(s.to_vec_padded(8)?.try_into().unwrap());
let product_key = Self { let product_key = Self {
upgrade, upgrade,
@ -223,10 +201,12 @@ impl ProductKey {
fn verify( fn verify(
&self, &self,
e_curve: &WeierstrassCurve, e_curve: &EcGroup,
base_point: &Point, base_point: &EcPoint,
public_key: &Point, public_key: &EcPoint,
) -> Result<bool> { ) -> Result<bool> {
let mut num_context = BigNumContext::new()?;
let data = self.channel_id << 1 | self.upgrade as u32; let data = self.channel_id << 1 | self.upgrade as u32;
let mut msg_buffer: [u8; SHA_MSG_LENGTH] = [0; SHA_MSG_LENGTH]; let mut msg_buffer: [u8; SHA_MSG_LENGTH] = [0; SHA_MSG_LENGTH];
@ -243,47 +223,39 @@ impl ProductKey {
msg_buffer[0x09] = 0x00; msg_buffer[0x09] = 0x00;
msg_buffer[0x0A] = 0x00; msg_buffer[0x0A] = 0x00;
let msg_digest = { let msg_digest = sha1(&msg_buffer[..=0x0A]);
let mut hasher = Sha1::new();
hasher.update(&msg_buffer[..=0x0A]);
hasher.finalize()
};
let i_signature = next_sn_bits(by_dword(&msg_digest[4..8]) as u64, 30, 2) << 32 let i_signature = next_sn_bits(by_dword(&msg_digest[4..8]) as u64, 30, 2) << 32
| by_dword(&msg_digest[0..4]) as u64; | by_dword(&msg_digest[0..4]) as u64;
let e = BigInt::from(i_signature); let e = BigNum::from_slice(&i_signature.to_be_bytes())?;
let s = BigInt::from(self.signature); let s = BigNum::from_slice(&self.signature.to_be_bytes())?;
let t = e_curve.multiply_point(&s, base_point); let mut x = BigNum::new()?;
let mut p = e_curve.multiply_point(&e, public_key); let mut y = BigNum::new()?;
p = e_curve.add_points(&t, &p); let mut p = EcPoint::new(e_curve)?;
p = e_curve.multiply_point(&s, &p); let mut t = EcPoint::new(e_curve)?;
let (x, y) = match p { t.mul(e_curve, base_point, &s, &num_context)?;
Point::Point { x, y } => (x, y), p.mul(e_curve, public_key, &e, &num_context)?;
Point::Infinity => bail!("Point at infinity!"),
};
let x_bin = x.to_bytes_le().1; {
let x_bin = if x_bin.len() < FIELD_BYTES { let p_2 = p.to_owned(e_curve)?;
(0..FIELD_BYTES - x_bin.len()) p.add(e_curve, &t, &p_2, &mut num_context)?;
.map(|_| 0) }
.chain(x_bin.into_iter())
.collect() {
} else { let p_2 = p.to_owned(e_curve)?;
x_bin p.mul(e_curve, &p_2, &s, &num_context)?;
}; }
let y_bin = y.to_bytes_le().1;
let y_bin = if y_bin.len() < FIELD_BYTES { p.affine_coordinates(e_curve, &mut x, &mut y, &mut num_context)?;
(0..FIELD_BYTES - y_bin.len())
.map(|_| 0) let mut x_bin = x.to_vec_padded(FIELD_BYTES as i32)?;
.chain(y_bin.into_iter()) x_bin.reverse();
.collect() let mut y_bin = y.to_vec_padded(FIELD_BYTES as i32)?;
} else { y_bin.reverse();
y_bin
};
msg_buffer[0x00] = 0x79; msg_buffer[0x00] = 0x79;
msg_buffer[0x01] = (data & 0x00FF) as u8; msg_buffer[0x01] = (data & 0x00FF) as u8;
@ -292,11 +264,7 @@ impl ProductKey {
msg_buffer[3..3 + FIELD_BYTES].copy_from_slice(&x_bin); msg_buffer[3..3 + FIELD_BYTES].copy_from_slice(&x_bin);
msg_buffer[3 + FIELD_BYTES..3 + FIELD_BYTES * 2].copy_from_slice(&y_bin); msg_buffer[3 + FIELD_BYTES..3 + FIELD_BYTES * 2].copy_from_slice(&y_bin);
let msg_digest = { let msg_digest = sha1(&msg_buffer);
let mut hasher = Sha1::new();
hasher.update(msg_buffer);
hasher.finalize()
};
let hash: u32 = by_dword(&msg_digest[0..4]) & bitmask(31) as u32; let hash: u32 = by_dword(&msg_digest[0..4]) & bitmask(31) as u32;
@ -385,12 +353,13 @@ mod tests {
let p = bink["p"].as_str().unwrap(); let p = bink["p"].as_str().unwrap();
let a = bink["a"].as_str().unwrap(); let a = bink["a"].as_str().unwrap();
let b = bink["b"].as_str().unwrap();
let gx = bink["g"]["x"].as_str().unwrap(); let gx = bink["g"]["x"].as_str().unwrap();
let gy = bink["g"]["y"].as_str().unwrap(); let gy = bink["g"]["y"].as_str().unwrap();
let kx = bink["pub"]["x"].as_str().unwrap(); let kx = bink["pub"]["x"].as_str().unwrap();
let ky = bink["pub"]["y"].as_str().unwrap(); let ky = bink["pub"]["y"].as_str().unwrap();
let curve = EllipticCurve::new(p, a, gx, gy, kx, ky).unwrap(); let curve = EllipticCurve::new(p, a, b, gx, gy, kx, ky).unwrap();
assert!(super::ProductKey::from_key(&curve, product_key).is_ok()); assert!(super::ProductKey::from_key(&curve, product_key).is_ok());
assert!(super::ProductKey::from_key(&curve, "11111-YRGC8-4KYTG-C3FCC-JCFDY").is_err()); assert!(super::ProductKey::from_key(&curve, "11111-YRGC8-4KYTG-C3FCC-JCFDY").is_err());

View file

@ -1,24 +1,24 @@
use anyhow::Result; use anyhow::Result;
use num_bigint::BigInt; use openssl::{
use num_traits::Num; bn::{BigNum, BigNumContext},
ec::{EcGroup, EcPoint},
use crate::weierstrass_curve::{Point, WeierstrassCurve}; };
pub struct EllipticCurve { pub struct EllipticCurve {
pub curve: WeierstrassCurve, pub curve: EcGroup,
pub gen_point: Point, pub gen_point: EcPoint,
pub pub_point: Point, pub pub_point: EcPoint,
} }
pub struct PrivateKey { pub struct PrivateKey {
pub gen_order: BigInt, pub gen_order: BigNum,
pub private_key: BigInt, pub private_key: BigNum,
} }
impl PrivateKey { impl PrivateKey {
pub fn new(gen_order: &str, private_key: &str) -> Result<Self> { pub fn new(gen_order: &str, private_key: &str) -> Result<Self> {
let gen_order = BigInt::from_str_radix(gen_order, 10)?; let gen_order = BigNum::from_dec_str(gen_order)?;
let private_key = BigInt::from_str_radix(private_key, 10)?; let private_key = &gen_order - &BigNum::from_dec_str(private_key)?;
Ok(Self { Ok(Self {
gen_order, gen_order,
private_key, private_key,
@ -30,29 +30,29 @@ impl EllipticCurve {
pub fn new( pub fn new(
p: &str, p: &str,
a: &str, a: &str,
b: &str,
generator_x: &str, generator_x: &str,
generator_y: &str, generator_y: &str,
public_key_x: &str, public_key_x: &str,
public_key_y: &str, public_key_y: &str,
) -> Result<Self> { ) -> Result<Self> {
let p = BigInt::from_str_radix(p, 10)?; let mut context = BigNumContext::new()?;
let a = BigInt::from_str_radix(a, 10)?;
let generator_x = BigInt::from_str_radix(generator_x, 10)?;
let generator_y = BigInt::from_str_radix(generator_y, 10)?;
let public_key_x = BigInt::from_str_radix(public_key_x, 10)?;
let public_key_y = BigInt::from_str_radix(public_key_y, 10)?;
let curve = WeierstrassCurve::new(a, p); let p = BigNum::from_dec_str(p)?;
let a = BigNum::from_dec_str(a)?;
let b = BigNum::from_dec_str(b)?;
let generator_x = BigNum::from_dec_str(generator_x)?;
let generator_y = BigNum::from_dec_str(generator_y)?;
let public_key_x = BigNum::from_dec_str(public_key_x)?;
let public_key_y = BigNum::from_dec_str(public_key_y)?;
let gen_point = Point::Point { let curve = EcGroup::from_components(p, a, b, &mut context)?;
x: generator_x,
y: generator_y,
};
let pub_point = Point::Point { let mut gen_point = EcPoint::new(&curve)?;
x: public_key_x, gen_point.set_affine_coordinates_gfp(&curve, &generator_x, &generator_y, &mut context)?;
y: public_key_y,
}; let mut pub_point = EcPoint::new(&curve)?;
pub_point.set_affine_coordinates_gfp(&curve, &public_key_x, &public_key_y, &mut context)?;
Ok(Self { Ok(Self {
curve, curve,

View file

@ -1,9 +1,7 @@
use std::collections::VecDeque; use std::collections::VecDeque;
use anyhow::{anyhow, Result}; use anyhow::{anyhow, Result};
use num_bigint::{BigInt, Sign}; use openssl::bn::BigNum;
use num_integer::Integer;
use num_traits::{ToPrimitive, Zero};
const PK_LENGTH: usize = 25; const PK_LENGTH: usize = 25;
@ -19,24 +17,20 @@ pub(crate) fn base24_decode(cd_key: &str) -> Result<Vec<u8>> {
.filter_map(|c| KEY_CHARSET.iter().position(|&x| x == c).map(|i| i as u8)) .filter_map(|c| KEY_CHARSET.iter().position(|&x| x == c).map(|i| i as u8))
.collect(); .collect();
let mut y = BigInt::zero(); let mut y = BigNum::from_u32(0).unwrap();
for i in decoded_key { for i in decoded_key {
y *= PK_LENGTH - 1; y.mul_word((PK_LENGTH - 1) as u32).unwrap();
y += i as u32; y.add_word(i.into()).unwrap();
} }
Ok(y.to_bytes_be().1) Ok(y.to_vec())
} }
pub(crate) fn base24_encode(byte_seq: &[u8]) -> Result<String> { pub(crate) fn base24_encode(byte_seq: &[u8]) -> Result<String> {
let mut z = BigInt::from_bytes_be(Sign::Plus, byte_seq); let mut z = BigNum::from_slice(byte_seq).unwrap();
let mut out: VecDeque<char> = VecDeque::new(); let mut out: VecDeque<char> = VecDeque::new();
(0..=24).for_each(|_| { (0..=24).for_each(|_| out.push_front(KEY_CHARSET[z.div_word(24).unwrap() as usize]));
let (quo, rem) = z.div_rem(&BigInt::from(24));
z = quo;
out.push_front(KEY_CHARSET[rem.to_u32().unwrap() as usize]);
});
Ok(out.iter().collect()) Ok(out.iter().collect())
} }

View file

@ -4,5 +4,3 @@ pub mod confid;
pub mod crypto; pub mod crypto;
mod key; mod key;
mod math; mod math;
mod msr;
mod weierstrass_curve;

View file

@ -1,61 +0,0 @@
use num_bigint::BigInt;
use num_traits::{One, Zero};
// Legendre symbol, returns 1, 0, or -1 mod p
fn ls(a: &BigInt, p: &BigInt) -> BigInt {
let exp = (p - BigInt::one()) / BigInt::from(2);
a.modpow(&exp, p)
}
// Tonelli-Shanks algorithm
pub fn mod_sqrt(n: &BigInt, p: &BigInt) -> Option<BigInt> {
if !ls(n, p).is_one() {
return None;
}
let mut q = p - 1;
let mut s = BigInt::zero();
while (&q & &BigInt::one()).is_zero() {
s += 1;
q >>= 1
}
if s.is_one() {
let exp = (p + 1) / 4;
let r1 = n.modpow(&exp, p);
return Some(p - &r1);
}
let mut z = BigInt::from(2);
while ls(&z, p) != p - 1 {
z += 1
}
let mut c = z.modpow(&q, p);
let mut r = n.modpow(&((&q + 1) / 2), p);
let mut t = n.modpow(&q, p);
let mut m = s;
loop {
if t.is_one() {
return Some(p - &r);
}
let mut i = BigInt::zero();
let mut z = t.clone();
let mut b = c.clone();
while !z.is_one() && i < &m - 1 {
z = &z * &z % p;
i += 1;
}
let mut e = &m - &i - 1;
while e > BigInt::zero() {
b = &b * &b % p;
e -= 1;
}
r = &r * &b % p;
c = &b * &b % p;
t = &t * &c % p;
m = i;
}
}

View file

@ -1,88 +0,0 @@
use num_bigint::BigInt;
use num_integer::Integer;
use num_traits::{One, Zero};
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Point {
Infinity,
Point { x: BigInt, y: BigInt },
}
#[derive(Debug, Clone)]
pub struct WeierstrassCurve {
a: BigInt,
p: BigInt,
}
impl WeierstrassCurve {
pub fn new(a: BigInt, p: BigInt) -> Self {
WeierstrassCurve { a, p }
}
fn mod_inverse(a: &BigInt, p: &BigInt) -> BigInt {
let egcd = a.extended_gcd(p);
egcd.x.mod_floor(p)
}
fn double_point(&self, point: &Point) -> Point {
match point {
Point::Point { x, y } => {
if y.is_zero() {
Point::Infinity
} else {
let three = BigInt::from(3);
let two = BigInt::from(2);
let lambda = (three * x * x + &self.a) * Self::mod_inverse(&(two * y), &self.p);
let lamba_sqr = (&lambda * &lambda).mod_floor(&self.p);
let x3 = (&lamba_sqr - x - x).mod_floor(&self.p);
let y3 = (&lambda * (x - &x3) - y).mod_floor(&self.p);
Point::Point { x: x3, y: y3 }
}
}
Point::Infinity => Point::Infinity,
}
}
pub fn add_points(&self, point1: &Point, point2: &Point) -> Point {
match (point1, point2) {
(Point::Point { x: x1, y: y1 }, Point::Point { x: x2, y: y2 }) => {
if point1 == point2 {
self.double_point(point1)
} else {
let lambda = (y2 - y1) * Self::mod_inverse(&(x2 - x1), &self.p);
let x3 = ((&lambda * &lambda) - x1 - x2).mod_floor(&self.p);
let y3: BigInt = ((&lambda * (x1 - &x3)) - y1).mod_floor(&self.p);
Point::Point { x: x3, y: y3 }
}
}
(Point::Point { x, y }, Point::Infinity) | (Point::Infinity, Point::Point { x, y }) => {
Point::Point {
x: x.clone(),
y: y.clone(),
}
}
(Point::Infinity, Point::Infinity) => Point::Infinity,
}
}
pub fn multiply_point(&self, s: &BigInt, point: &Point) -> Point {
let mut res = Point::Infinity;
let mut temp = point.clone();
let mut s = s.clone();
while s > BigInt::zero() {
if (&s % BigInt::from(2)) == BigInt::one() {
res = self.add_points(&res, &temp);
}
temp = self.double_point(&temp);
s >>= 1;
}
res
}
}

View file

@ -102,6 +102,7 @@ fn validate(args: &ValidateArgs) -> Result<()> {
fn initialize_curve(bink: &Bink, bink_id: &str) -> Result<EllipticCurve> { fn initialize_curve(bink: &Bink, bink_id: &str) -> Result<EllipticCurve> {
let p = &bink.p; let p = &bink.p;
let a = &bink.a; let a = &bink.a;
let b = &bink.b;
let gx = &bink.g.x; let gx = &bink.g.x;
let gy = &bink.g.y; let gy = &bink.g.y;
let kx = &bink.public.x; let kx = &bink.public.x;
@ -109,7 +110,7 @@ fn initialize_curve(bink: &Bink, bink_id: &str) -> Result<EllipticCurve> {
log::info!("Elliptic curve parameters for BINK ID {bink_id}:\n{bink}"); log::info!("Elliptic curve parameters for BINK ID {bink_id}:\n{bink}");
EllipticCurve::new(p, a, gx, gy, kx, ky) EllipticCurve::new(p, a, b, gx, gy, kx, ky)
} }
fn bink1998_generate( fn bink1998_generate(