diff --git a/.gitignore b/.gitignore
index 974afb8..81cf465 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,2 @@
/target
/.vscode
-keys.json
diff --git a/Cargo.lock b/Cargo.lock
index 872cbbe..015dce4 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -57,18 +57,6 @@ version = "1.0.71"
source = "registry+https://github.com/rust-lang/crates.io-index"
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]]
name = "bitflags"
version = "1.3.2"
@@ -84,15 +72,6 @@ dependencies = [
"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]]
name = "cc"
version = "1.0.79"
@@ -153,63 +132,6 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
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]]
name = "errno"
version = "0.3.1"
@@ -232,47 +154,19 @@ dependencies = [
]
[[package]]
-name = "ff"
-version = "0.13.0"
+name = "foreign-types"
+version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449"
+checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
dependencies = [
- "rand_core",
- "subtle",
+ "foreign-types-shared",
]
[[package]]
-name = "generic-array"
-version = "0.14.7"
+name = "foreign-types-shared"
+version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
-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",
-]
+checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
[[package]]
name = "heck"
@@ -333,50 +227,6 @@ version = "0.4.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4"
-[[package]]
-name = "mskey"
-version = "0.1.0"
-dependencies = [
- "anyhow",
- "clap",
- "log",
- "serde",
- "serde_json",
- "simple_logger",
- "umskt",
-]
-
-[[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]]
name = "once_cell"
version = "1.18.0"
@@ -384,10 +234,45 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
[[package]]
-name = "ppv-lite86"
-version = "0.2.17"
+name = "openssl"
+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"
-checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
+checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964"
[[package]]
name = "proc-macro2"
@@ -407,36 +292,6 @@ dependencies = [
"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]]
name = "rustix"
version = "0.37.20"
@@ -488,17 +343,6 @@ dependencies = [
"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]]
name = "simple_logger"
version = "4.2.0"
@@ -515,12 +359,6 @@ version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
-[[package]]
-name = "subtle"
-version = "2.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc"
-
[[package]]
name = "syn"
version = "2.0.21"
@@ -552,25 +390,14 @@ dependencies = [
"syn",
]
-[[package]]
-name = "typenum"
-version = "1.16.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba"
-
[[package]]
name = "umskt"
version = "0.1.0"
dependencies = [
"anyhow",
"bitreader",
- "elliptic-curve",
- "num-bigint",
- "num-integer",
- "num-traits",
- "rand",
+ "openssl",
"serde_json",
- "sha1",
"thiserror",
]
@@ -587,16 +414,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
[[package]]
-name = "version_check"
-version = "0.9.4"
+name = "vcpkg"
+version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
-
-[[package]]
-name = "wasi"
-version = "0.11.0+wasi-snapshot-preview1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
+checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
[[package]]
name = "windows-sys"
@@ -722,7 +543,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a"
[[package]]
-name = "zeroize"
-version = "1.6.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9"
+name = "xpkey"
+version = "0.1.0"
+dependencies = [
+ "anyhow",
+ "clap",
+ "log",
+ "serde",
+ "serde_json",
+ "simple_logger",
+ "umskt",
+]
diff --git a/Cargo.toml b/Cargo.toml
index 31a9228..cd188fb 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,15 +1,6 @@
[workspace]
-resolver = "2"
members = [
"umskt",
- "mskey",
+ "xpkey",
]
-
-[profile.release]
-lto = true
-
-[profile.release.package.mskey]
-strip = true
-opt-level = "z"
-codegen-units = 1
diff --git a/LICENSE b/LICENSE
deleted file mode 100644
index 1ce8758..0000000
--- a/LICENSE
+++ /dev/null
@@ -1,661 +0,0 @@
- GNU AFFERO GENERAL PUBLIC LICENSE
- Version 3, 19 November 2007
-
- Copyright (C) 2007 Free Software Foundation, Inc.
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
- Preamble
-
- The GNU Affero General Public License is a free, copyleft license for
-software and other kinds of works, specifically designed to ensure
-cooperation with the community in the case of network server software.
-
- The licenses for most software and other practical works are designed
-to take away your freedom to share and change the works. By contrast,
-our General Public Licenses are intended to guarantee your freedom to
-share and change all versions of a program--to make sure it remains free
-software for all its users.
-
- When we speak of free software, we are referring to freedom, not
-price. Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-them if you wish), that you receive source code or can get it if you
-want it, that you can change the software or use pieces of it in new
-free programs, and that you know you can do these things.
-
- Developers that use our General Public Licenses protect your rights
-with two steps: (1) assert copyright on the software, and (2) offer
-you this License which gives you legal permission to copy, distribute
-and/or modify the software.
-
- A secondary benefit of defending all users' freedom is that
-improvements made in alternate versions of the program, if they
-receive widespread use, become available for other developers to
-incorporate. Many developers of free software are heartened and
-encouraged by the resulting cooperation. However, in the case of
-software used on network servers, this result may fail to come about.
-The GNU General Public License permits making a modified version and
-letting the public access it on a server without ever releasing its
-source code to the public.
-
- The GNU Affero General Public License is designed specifically to
-ensure that, in such cases, the modified source code becomes available
-to the community. It requires the operator of a network server to
-provide the source code of the modified version running there to the
-users of that server. Therefore, public use of a modified version, on
-a publicly accessible server, gives the public access to the source
-code of the modified version.
-
- An older license, called the Affero General Public License and
-published by Affero, was designed to accomplish similar goals. This is
-a different license, not a version of the Affero GPL, but Affero has
-released a new version of the Affero GPL which permits relicensing under
-this license.
-
- The precise terms and conditions for copying, distribution and
-modification follow.
-
- TERMS AND CONDITIONS
-
- 0. Definitions.
-
- "This License" refers to version 3 of the GNU Affero General Public License.
-
- "Copyright" also means copyright-like laws that apply to other kinds of
-works, such as semiconductor masks.
-
- "The Program" refers to any copyrightable work licensed under this
-License. Each licensee is addressed as "you". "Licensees" and
-"recipients" may be individuals or organizations.
-
- To "modify" a work means to copy from or adapt all or part of the work
-in a fashion requiring copyright permission, other than the making of an
-exact copy. The resulting work is called a "modified version" of the
-earlier work or a work "based on" the earlier work.
-
- A "covered work" means either the unmodified Program or a work based
-on the Program.
-
- To "propagate" a work means to do anything with it that, without
-permission, would make you directly or secondarily liable for
-infringement under applicable copyright law, except executing it on a
-computer or modifying a private copy. Propagation includes copying,
-distribution (with or without modification), making available to the
-public, and in some countries other activities as well.
-
- To "convey" a work means any kind of propagation that enables other
-parties to make or receive copies. Mere interaction with a user through
-a computer network, with no transfer of a copy, is not conveying.
-
- An interactive user interface displays "Appropriate Legal Notices"
-to the extent that it includes a convenient and prominently visible
-feature that (1) displays an appropriate copyright notice, and (2)
-tells the user that there is no warranty for the work (except to the
-extent that warranties are provided), that licensees may convey the
-work under this License, and how to view a copy of this License. If
-the interface presents a list of user commands or options, such as a
-menu, a prominent item in the list meets this criterion.
-
- 1. Source Code.
-
- The "source code" for a work means the preferred form of the work
-for making modifications to it. "Object code" means any non-source
-form of a work.
-
- A "Standard Interface" means an interface that either is an official
-standard defined by a recognized standards body, or, in the case of
-interfaces specified for a particular programming language, one that
-is widely used among developers working in that language.
-
- The "System Libraries" of an executable work include anything, other
-than the work as a whole, that (a) is included in the normal form of
-packaging a Major Component, but which is not part of that Major
-Component, and (b) serves only to enable use of the work with that
-Major Component, or to implement a Standard Interface for which an
-implementation is available to the public in source code form. A
-"Major Component", in this context, means a major essential component
-(kernel, window system, and so on) of the specific operating system
-(if any) on which the executable work runs, or a compiler used to
-produce the work, or an object code interpreter used to run it.
-
- The "Corresponding Source" for a work in object code form means all
-the source code needed to generate, install, and (for an executable
-work) run the object code and to modify the work, including scripts to
-control those activities. However, it does not include the work's
-System Libraries, or general-purpose tools or generally available free
-programs which are used unmodified in performing those activities but
-which are not part of the work. For example, Corresponding Source
-includes interface definition files associated with source files for
-the work, and the source code for shared libraries and dynamically
-linked subprograms that the work is specifically designed to require,
-such as by intimate data communication or control flow between those
-subprograms and other parts of the work.
-
- The Corresponding Source need not include anything that users
-can regenerate automatically from other parts of the Corresponding
-Source.
-
- The Corresponding Source for a work in source code form is that
-same work.
-
- 2. Basic Permissions.
-
- All rights granted under this License are granted for the term of
-copyright on the Program, and are irrevocable provided the stated
-conditions are met. This License explicitly affirms your unlimited
-permission to run the unmodified Program. The output from running a
-covered work is covered by this License only if the output, given its
-content, constitutes a covered work. This License acknowledges your
-rights of fair use or other equivalent, as provided by copyright law.
-
- You may make, run and propagate covered works that you do not
-convey, without conditions so long as your license otherwise remains
-in force. You may convey covered works to others for the sole purpose
-of having them make modifications exclusively for you, or provide you
-with facilities for running those works, provided that you comply with
-the terms of this License in conveying all material for which you do
-not control copyright. Those thus making or running the covered works
-for you must do so exclusively on your behalf, under your direction
-and control, on terms that prohibit them from making any copies of
-your copyrighted material outside their relationship with you.
-
- Conveying under any other circumstances is permitted solely under
-the conditions stated below. Sublicensing is not allowed; section 10
-makes it unnecessary.
-
- 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
-
- No covered work shall be deemed part of an effective technological
-measure under any applicable law fulfilling obligations under article
-11 of the WIPO copyright treaty adopted on 20 December 1996, or
-similar laws prohibiting or restricting circumvention of such
-measures.
-
- When you convey a covered work, you waive any legal power to forbid
-circumvention of technological measures to the extent such circumvention
-is effected by exercising rights under this License with respect to
-the covered work, and you disclaim any intention to limit operation or
-modification of the work as a means of enforcing, against the work's
-users, your or third parties' legal rights to forbid circumvention of
-technological measures.
-
- 4. Conveying Verbatim Copies.
-
- You may convey verbatim copies of the Program's source code as you
-receive it, in any medium, provided that you conspicuously and
-appropriately publish on each copy an appropriate copyright notice;
-keep intact all notices stating that this License and any
-non-permissive terms added in accord with section 7 apply to the code;
-keep intact all notices of the absence of any warranty; and give all
-recipients a copy of this License along with the Program.
-
- You may charge any price or no price for each copy that you convey,
-and you may offer support or warranty protection for a fee.
-
- 5. Conveying Modified Source Versions.
-
- You may convey a work based on the Program, or the modifications to
-produce it from the Program, in the form of source code under the
-terms of section 4, provided that you also meet all of these conditions:
-
- a) The work must carry prominent notices stating that you modified
- it, and giving a relevant date.
-
- b) The work must carry prominent notices stating that it is
- released under this License and any conditions added under section
- 7. This requirement modifies the requirement in section 4 to
- "keep intact all notices".
-
- c) You must license the entire work, as a whole, under this
- License to anyone who comes into possession of a copy. This
- License will therefore apply, along with any applicable section 7
- additional terms, to the whole of the work, and all its parts,
- regardless of how they are packaged. This License gives no
- permission to license the work in any other way, but it does not
- invalidate such permission if you have separately received it.
-
- d) If the work has interactive user interfaces, each must display
- Appropriate Legal Notices; however, if the Program has interactive
- interfaces that do not display Appropriate Legal Notices, your
- work need not make them do so.
-
- A compilation of a covered work with other separate and independent
-works, which are not by their nature extensions of the covered work,
-and which are not combined with it such as to form a larger program,
-in or on a volume of a storage or distribution medium, is called an
-"aggregate" if the compilation and its resulting copyright are not
-used to limit the access or legal rights of the compilation's users
-beyond what the individual works permit. Inclusion of a covered work
-in an aggregate does not cause this License to apply to the other
-parts of the aggregate.
-
- 6. Conveying Non-Source Forms.
-
- You may convey a covered work in object code form under the terms
-of sections 4 and 5, provided that you also convey the
-machine-readable Corresponding Source under the terms of this License,
-in one of these ways:
-
- a) Convey the object code in, or embodied in, a physical product
- (including a physical distribution medium), accompanied by the
- Corresponding Source fixed on a durable physical medium
- customarily used for software interchange.
-
- b) Convey the object code in, or embodied in, a physical product
- (including a physical distribution medium), accompanied by a
- written offer, valid for at least three years and valid for as
- long as you offer spare parts or customer support for that product
- model, to give anyone who possesses the object code either (1) a
- copy of the Corresponding Source for all the software in the
- product that is covered by this License, on a durable physical
- medium customarily used for software interchange, for a price no
- more than your reasonable cost of physically performing this
- conveying of source, or (2) access to copy the
- Corresponding Source from a network server at no charge.
-
- c) Convey individual copies of the object code with a copy of the
- written offer to provide the Corresponding Source. This
- alternative is allowed only occasionally and noncommercially, and
- only if you received the object code with such an offer, in accord
- with subsection 6b.
-
- d) Convey the object code by offering access from a designated
- place (gratis or for a charge), and offer equivalent access to the
- Corresponding Source in the same way through the same place at no
- further charge. You need not require recipients to copy the
- Corresponding Source along with the object code. If the place to
- copy the object code is a network server, the Corresponding Source
- may be on a different server (operated by you or a third party)
- that supports equivalent copying facilities, provided you maintain
- clear directions next to the object code saying where to find the
- Corresponding Source. Regardless of what server hosts the
- Corresponding Source, you remain obligated to ensure that it is
- available for as long as needed to satisfy these requirements.
-
- e) Convey the object code using peer-to-peer transmission, provided
- you inform other peers where the object code and Corresponding
- Source of the work are being offered to the general public at no
- charge under subsection 6d.
-
- A separable portion of the object code, whose source code is excluded
-from the Corresponding Source as a System Library, need not be
-included in conveying the object code work.
-
- A "User Product" is either (1) a "consumer product", which means any
-tangible personal property which is normally used for personal, family,
-or household purposes, or (2) anything designed or sold for incorporation
-into a dwelling. In determining whether a product is a consumer product,
-doubtful cases shall be resolved in favor of coverage. For a particular
-product received by a particular user, "normally used" refers to a
-typical or common use of that class of product, regardless of the status
-of the particular user or of the way in which the particular user
-actually uses, or expects or is expected to use, the product. A product
-is a consumer product regardless of whether the product has substantial
-commercial, industrial or non-consumer uses, unless such uses represent
-the only significant mode of use of the product.
-
- "Installation Information" for a User Product means any methods,
-procedures, authorization keys, or other information required to install
-and execute modified versions of a covered work in that User Product from
-a modified version of its Corresponding Source. The information must
-suffice to ensure that the continued functioning of the modified object
-code is in no case prevented or interfered with solely because
-modification has been made.
-
- If you convey an object code work under this section in, or with, or
-specifically for use in, a User Product, and the conveying occurs as
-part of a transaction in which the right of possession and use of the
-User Product is transferred to the recipient in perpetuity or for a
-fixed term (regardless of how the transaction is characterized), the
-Corresponding Source conveyed under this section must be accompanied
-by the Installation Information. But this requirement does not apply
-if neither you nor any third party retains the ability to install
-modified object code on the User Product (for example, the work has
-been installed in ROM).
-
- The requirement to provide Installation Information does not include a
-requirement to continue to provide support service, warranty, or updates
-for a work that has been modified or installed by the recipient, or for
-the User Product in which it has been modified or installed. Access to a
-network may be denied when the modification itself materially and
-adversely affects the operation of the network or violates the rules and
-protocols for communication across the network.
-
- Corresponding Source conveyed, and Installation Information provided,
-in accord with this section must be in a format that is publicly
-documented (and with an implementation available to the public in
-source code form), and must require no special password or key for
-unpacking, reading or copying.
-
- 7. Additional Terms.
-
- "Additional permissions" are terms that supplement the terms of this
-License by making exceptions from one or more of its conditions.
-Additional permissions that are applicable to the entire Program shall
-be treated as though they were included in this License, to the extent
-that they are valid under applicable law. If additional permissions
-apply only to part of the Program, that part may be used separately
-under those permissions, but the entire Program remains governed by
-this License without regard to the additional permissions.
-
- When you convey a copy of a covered work, you may at your option
-remove any additional permissions from that copy, or from any part of
-it. (Additional permissions may be written to require their own
-removal in certain cases when you modify the work.) You may place
-additional permissions on material, added by you to a covered work,
-for which you have or can give appropriate copyright permission.
-
- Notwithstanding any other provision of this License, for material you
-add to a covered work, you may (if authorized by the copyright holders of
-that material) supplement the terms of this License with terms:
-
- a) Disclaiming warranty or limiting liability differently from the
- terms of sections 15 and 16 of this License; or
-
- b) Requiring preservation of specified reasonable legal notices or
- author attributions in that material or in the Appropriate Legal
- Notices displayed by works containing it; or
-
- c) Prohibiting misrepresentation of the origin of that material, or
- requiring that modified versions of such material be marked in
- reasonable ways as different from the original version; or
-
- d) Limiting the use for publicity purposes of names of licensors or
- authors of the material; or
-
- e) Declining to grant rights under trademark law for use of some
- trade names, trademarks, or service marks; or
-
- f) Requiring indemnification of licensors and authors of that
- material by anyone who conveys the material (or modified versions of
- it) with contractual assumptions of liability to the recipient, for
- any liability that these contractual assumptions directly impose on
- those licensors and authors.
-
- All other non-permissive additional terms are considered "further
-restrictions" within the meaning of section 10. If the Program as you
-received it, or any part of it, contains a notice stating that it is
-governed by this License along with a term that is a further
-restriction, you may remove that term. If a license document contains
-a further restriction but permits relicensing or conveying under this
-License, you may add to a covered work material governed by the terms
-of that license document, provided that the further restriction does
-not survive such relicensing or conveying.
-
- If you add terms to a covered work in accord with this section, you
-must place, in the relevant source files, a statement of the
-additional terms that apply to those files, or a notice indicating
-where to find the applicable terms.
-
- Additional terms, permissive or non-permissive, may be stated in the
-form of a separately written license, or stated as exceptions;
-the above requirements apply either way.
-
- 8. Termination.
-
- You may not propagate or modify a covered work except as expressly
-provided under this License. Any attempt otherwise to propagate or
-modify it is void, and will automatically terminate your rights under
-this License (including any patent licenses granted under the third
-paragraph of section 11).
-
- However, if you cease all violation of this License, then your
-license from a particular copyright holder is reinstated (a)
-provisionally, unless and until the copyright holder explicitly and
-finally terminates your license, and (b) permanently, if the copyright
-holder fails to notify you of the violation by some reasonable means
-prior to 60 days after the cessation.
-
- Moreover, your license from a particular copyright holder is
-reinstated permanently if the copyright holder notifies you of the
-violation by some reasonable means, this is the first time you have
-received notice of violation of this License (for any work) from that
-copyright holder, and you cure the violation prior to 30 days after
-your receipt of the notice.
-
- Termination of your rights under this section does not terminate the
-licenses of parties who have received copies or rights from you under
-this License. If your rights have been terminated and not permanently
-reinstated, you do not qualify to receive new licenses for the same
-material under section 10.
-
- 9. Acceptance Not Required for Having Copies.
-
- You are not required to accept this License in order to receive or
-run a copy of the Program. Ancillary propagation of a covered work
-occurring solely as a consequence of using peer-to-peer transmission
-to receive a copy likewise does not require acceptance. However,
-nothing other than this License grants you permission to propagate or
-modify any covered work. These actions infringe copyright if you do
-not accept this License. Therefore, by modifying or propagating a
-covered work, you indicate your acceptance of this License to do so.
-
- 10. Automatic Licensing of Downstream Recipients.
-
- Each time you convey a covered work, the recipient automatically
-receives a license from the original licensors, to run, modify and
-propagate that work, subject to this License. You are not responsible
-for enforcing compliance by third parties with this License.
-
- An "entity transaction" is a transaction transferring control of an
-organization, or substantially all assets of one, or subdividing an
-organization, or merging organizations. If propagation of a covered
-work results from an entity transaction, each party to that
-transaction who receives a copy of the work also receives whatever
-licenses to the work the party's predecessor in interest had or could
-give under the previous paragraph, plus a right to possession of the
-Corresponding Source of the work from the predecessor in interest, if
-the predecessor has it or can get it with reasonable efforts.
-
- You may not impose any further restrictions on the exercise of the
-rights granted or affirmed under this License. For example, you may
-not impose a license fee, royalty, or other charge for exercise of
-rights granted under this License, and you may not initiate litigation
-(including a cross-claim or counterclaim in a lawsuit) alleging that
-any patent claim is infringed by making, using, selling, offering for
-sale, or importing the Program or any portion of it.
-
- 11. Patents.
-
- A "contributor" is a copyright holder who authorizes use under this
-License of the Program or a work on which the Program is based. The
-work thus licensed is called the contributor's "contributor version".
-
- A contributor's "essential patent claims" are all patent claims
-owned or controlled by the contributor, whether already acquired or
-hereafter acquired, that would be infringed by some manner, permitted
-by this License, of making, using, or selling its contributor version,
-but do not include claims that would be infringed only as a
-consequence of further modification of the contributor version. For
-purposes of this definition, "control" includes the right to grant
-patent sublicenses in a manner consistent with the requirements of
-this License.
-
- Each contributor grants you a non-exclusive, worldwide, royalty-free
-patent license under the contributor's essential patent claims, to
-make, use, sell, offer for sale, import and otherwise run, modify and
-propagate the contents of its contributor version.
-
- In the following three paragraphs, a "patent license" is any express
-agreement or commitment, however denominated, not to enforce a patent
-(such as an express permission to practice a patent or covenant not to
-sue for patent infringement). To "grant" such a patent license to a
-party means to make such an agreement or commitment not to enforce a
-patent against the party.
-
- If you convey a covered work, knowingly relying on a patent license,
-and the Corresponding Source of the work is not available for anyone
-to copy, free of charge and under the terms of this License, through a
-publicly available network server or other readily accessible means,
-then you must either (1) cause the Corresponding Source to be so
-available, or (2) arrange to deprive yourself of the benefit of the
-patent license for this particular work, or (3) arrange, in a manner
-consistent with the requirements of this License, to extend the patent
-license to downstream recipients. "Knowingly relying" means you have
-actual knowledge that, but for the patent license, your conveying the
-covered work in a country, or your recipient's use of the covered work
-in a country, would infringe one or more identifiable patents in that
-country that you have reason to believe are valid.
-
- If, pursuant to or in connection with a single transaction or
-arrangement, you convey, or propagate by procuring conveyance of, a
-covered work, and grant a patent license to some of the parties
-receiving the covered work authorizing them to use, propagate, modify
-or convey a specific copy of the covered work, then the patent license
-you grant is automatically extended to all recipients of the covered
-work and works based on it.
-
- A patent license is "discriminatory" if it does not include within
-the scope of its coverage, prohibits the exercise of, or is
-conditioned on the non-exercise of one or more of the rights that are
-specifically granted under this License. You may not convey a covered
-work if you are a party to an arrangement with a third party that is
-in the business of distributing software, under which you make payment
-to the third party based on the extent of your activity of conveying
-the work, and under which the third party grants, to any of the
-parties who would receive the covered work from you, a discriminatory
-patent license (a) in connection with copies of the covered work
-conveyed by you (or copies made from those copies), or (b) primarily
-for and in connection with specific products or compilations that
-contain the covered work, unless you entered into that arrangement,
-or that patent license was granted, prior to 28 March 2007.
-
- Nothing in this License shall be construed as excluding or limiting
-any implied license or other defenses to infringement that may
-otherwise be available to you under applicable patent law.
-
- 12. No Surrender of Others' Freedom.
-
- If conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License. If you cannot convey a
-covered work so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you may
-not convey it at all. For example, if you agree to terms that obligate you
-to collect a royalty for further conveying from those to whom you convey
-the Program, the only way you could satisfy both those terms and this
-License would be to refrain entirely from conveying the Program.
-
- 13. Remote Network Interaction; Use with the GNU General Public License.
-
- Notwithstanding any other provision of this License, if you modify the
-Program, your modified version must prominently offer all users
-interacting with it remotely through a computer network (if your version
-supports such interaction) an opportunity to receive the Corresponding
-Source of your version by providing access to the Corresponding Source
-from a network server at no charge, through some standard or customary
-means of facilitating copying of software. This Corresponding Source
-shall include the Corresponding Source for any work covered by version 3
-of the GNU General Public License that is incorporated pursuant to the
-following paragraph.
-
- Notwithstanding any other provision of this License, you have
-permission to link or combine any covered work with a work licensed
-under version 3 of the GNU General Public License into a single
-combined work, and to convey the resulting work. The terms of this
-License will continue to apply to the part which is the covered work,
-but the work with which it is combined will remain governed by version
-3 of the GNU General Public License.
-
- 14. Revised Versions of this License.
-
- The Free Software Foundation may publish revised and/or new versions of
-the GNU Affero General Public License from time to time. Such new versions
-will be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
- Each version is given a distinguishing version number. If the
-Program specifies that a certain numbered version of the GNU Affero General
-Public License "or any later version" applies to it, you have the
-option of following the terms and conditions either of that numbered
-version or of any later version published by the Free Software
-Foundation. If the Program does not specify a version number of the
-GNU Affero General Public License, you may choose any version ever published
-by the Free Software Foundation.
-
- If the Program specifies that a proxy can decide which future
-versions of the GNU Affero General Public License can be used, that proxy's
-public statement of acceptance of a version permanently authorizes you
-to choose that version for the Program.
-
- Later license versions may give you additional or different
-permissions. However, no additional obligations are imposed on any
-author or copyright holder as a result of your choosing to follow a
-later version.
-
- 15. Disclaimer of Warranty.
-
- THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
-APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
-HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
-OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
-THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
-IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
-ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
-
- 16. Limitation of Liability.
-
- IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
-THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
-GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
-USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
-DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
-PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
-EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
-SUCH DAMAGES.
-
- 17. Interpretation of Sections 15 and 16.
-
- If the disclaimer of warranty and limitation of liability provided
-above cannot be given local legal effect according to their terms,
-reviewing courts shall apply local law that most closely approximates
-an absolute waiver of all civil liability in connection with the
-Program, unless a warranty or assumption of liability accompanies a
-copy of the Program in return for a fee.
-
- END OF TERMS AND CONDITIONS
-
- How to Apply These Terms to Your New Programs
-
- If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
- To do so, attach the following notices to the program. It is safest
-to attach them to the start of each source file to most effectively
-state the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
-
- Copyright (C)
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as published
- by the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see .
-
-Also add information on how to contact you by electronic and paper mail.
-
- If your software can interact with users remotely through a computer
-network, you should also make sure that it provides a way for users to
-get its source. For example, if your program is a web application, its
-interface could display a "Source" link that leads users to an archive
-of the code. There are many ways you could offer source, and different
-solutions will be better for different programs; see section 13 for the
-specific requirements.
-
- You should also get your employer (if you work as a programmer) or school,
-if any, to sign a "copyright disclaimer" for the program, if necessary.
-For more information on this, and how to apply and follow the GNU AGPL, see
-.
\ No newline at end of file
diff --git a/README.md b/README.md
deleted file mode 100644
index 0bd7a37..0000000
--- a/README.md
+++ /dev/null
@@ -1,23 +0,0 @@
-# Universal MS Key Toolkit (UMSKT) Rust Edition
-
-This is an unofficial Rust port of the [UMSKT project](https://github.com/UMSKT/UMSKT/). It is a pure Rust implementation rather than a binding, so it does not require any C or C++ dependencies and can be built for any platform supported by Rust and std.
-
-It does not include the required keys.json file used by UMSKT. That needs to be found elsewhere, most likely in the UMSKT codebase.
-
-## Credits
-These contributors helped create the UMSKT project that this codebase was based on:
-* z22
-* MSKey
-* sk00ter
-* diamondggg
-* pottzman
-* Endermanch
-* Neo-Desktop
-* WitherOrNot
-* TheTank20
-
-## Development Requirements
-* [The Rust toolchain](https://rustup.rs/)
-
-## Build Steps
-1. `cargo build`
\ No newline at end of file
diff --git a/keys.json b/keys.json
new file mode 100644
index 0000000..6c174f7
--- /dev/null
+++ b/keys.json
@@ -0,0 +1,1571 @@
+{
+ "Products": {
+ "Windows CE Platform Builder 3": {
+ "BINK": ["00", "01", "0E", "0D", "0F"]
+ },
+ "Windows CE .Net Platform Builder 4": {
+ "BINK": ["00", "01"]
+ },
+ "Windows 98 (all)": {
+ "BINK": ["02","03"]
+ },
+ "Office 2000": {
+ "BINK": ["04", "05"]
+ },
+ "Internet Security and Acceleration (ISA) Server 2004": {
+ "BINK": ["06", "07"]
+ },
+ "PLUS! for Windows XP": {
+ "BINK": ["08", "09"]
+ },
+ "Windows 2000 Server (all)": {
+ "BINK": ["0A", "13"]
+ },
+ "Office Communicator 2007": {
+ "BINK": ["0C", "0D"]
+ },
+ "Windows Embedded POSReady 2009": {
+ "BINK": ["0D", "0D"]
+ },
+ "Windows CE .Net Platform Builder 5": {
+ "BINK": ["0D", "0D"]
+ },
+ "Commerce Server 2002": {
+ "BINK": ["0E", "0F"]
+ },
+ "Windows 2000 Professional": {
+ "BINK": ["12", "13"]
+ },
+ "Office for Mac 2004 / 2008": {
+ "BINK": ["18", "19"]
+ },
+ "Windows ME": {
+ "BINK": ["1C", "1D"]
+ },
+ "Office XP Applications": {
+ "BINK": ["20", "21"]
+ },
+ "Office XP": {
+ "BINK": ["22", "23"]
+ },
+ "Visual Studio .Net / .Net 2003": {
+ "BINK": ["24", "25"]
+ },
+ "Windows XP Professional Evaluation": {
+ "BINK": ["28", "29"]
+ },
+ "Windows XP Home": {
+ "BINK": ["2A", "2B"]
+ },
+ "Windows XP Pro": {
+ "BINK": ["2C", "2D"]
+ },
+ "Windows XP Pro IA-64": {
+ "BINK": ["2C", "2D"]
+ },
+ "Windows XP Pro VLK": {
+ "BINK": ["2E", "2F"]
+ },
+ "Windows XP Fundamentals for Legacy PCs": {
+ "BINK": ["2E", "2F"]
+ },
+ "Windows XP Professional K": {
+ "BINK": ["30", "31"]
+ },
+ "Windows XP Starter Edition": {
+ "BINK": ["32", "33"]
+ },
+ "Windows Longhorn (6.0.3683.0 -> 6.0.4029.0)": {
+ "BINK": ["40", "41"]
+ },
+ "Halo: Combat Evolved": {
+ "BINK": ["50", "51"]
+ },
+ "Halo: Custom Edition": {
+ "BINK": ["50", "51"]
+ },
+ "Visual Studio 2005": {
+ "BINK": ["52", "53"]
+ },
+ "Plus! Digital Media Edition for Windows XP": {
+ "BINK": ["52", "53"]
+ },
+ "Windows Longhorn (6.0.4033.0)": {
+ "BINK": ["54", "55"]
+ },
+ "Windows Server 2003": {
+ "BINK": ["54", "55", "58", "59"]
+ },
+ "Windows Server 2003 VLK": {
+ "BINK": ["5A", "5B"]
+ },
+ "Windows XP Pro 64 Bit Edition VLK": {
+ "BINK": ["64", "65"]
+ },
+ "Windows XP Pro 64 Bit Edition": {
+ "BINK": ["66", "67"]
+ },
+ "Windows Server 2003 64 Bit": {
+ "BINK": ["68", "69", "6C", "6D"]
+ },
+ "Windows Server 2003 64 Bit VLK": {
+ "BINK": ["68", "69", "6C", "6D"]
+ },
+ "Office 2003 Applications": {
+ "BINK": ["6E", "6F"]
+ },
+ "Office 2003 Small Business": {
+ "BINK": ["70", "71"]
+ },
+ "Office 2003 Professional": {
+ "BINK": ["72", "73"]
+ },
+ "Windows Longhorn (6.0.4039.0 -> Pre PIDGENX)": {
+ "BINK": ["74", "75"]
+ },
+ "Identity Lifecycle Manager 2007": {
+ "BINK": ["78", "79"]
+ },
+ "Visual Studio 2008": {
+ "BINK": ["78", "79"]
+ },
+ "Office 2007 Applications": {
+ "BINK": ["7E", "7F"]
+ },
+ "Office 2007 Basic / Small Business": {
+ "BINK": ["80", "81"]
+ },
+ "Office 2007 Standard / Professional / Ultimate / Enterprise": {
+ "BINK": ["82", "83"]
+ },
+ "Office 2007 Home & Student": {
+ "BINK": ["88", "89"]
+ }
+ },
+ "BINK": {
+ "00": {
+ "a": "1",
+ "b": "0",
+ "g": {
+ "x": "2331577204679600027736694662072998192243212592890122053374825500297155761496269562314159428299171097610055218913705",
+ "y": "3954018412338623664837114504916044126050878678856973124996251286784490174941479836757650135598751723409532967160444"
+ },
+ "n": "42464065991425877",
+ "p": "22771656396649042914677651938348976006738044330885828909690000917475479649330897416453073715484777125675617411561753",
+ "priv": "38647306188807670",
+ "pub": {
+ "x": "19001842596799889735847089805697287001733951474617682470323383968715961244343387245639296624260576737647372909452518",
+ "y": "5073995932966536731583795294253584537145351666788650220967374102582334986751283480528872642160868858730405130413714"
+ }
+ },
+ "01": {
+ "a": "1",
+ "b": "0",
+ "g": {
+ "x": "10673454940574675734218426124215696222570049943204897295660707733776259469307290746763087579272352204477426359456983",
+ "y": "12266547372348718976150807658375668076642952085819513623587674808420656632476917449122499280756388746447098580732795"
+ },
+ "n": "45451421528219701",
+ "p": "21690482571471944131858536333908058782272452491831771308020961342630740764170913541267450561542337158596383516743897",
+ "priv": "17403239656857625",
+ "pub": {
+ "x": "3614099199023017971148876036659975837782690680728273254586906030102722523955367121942849829253953580887060503496633",
+ "y": "13800594939586205538166670892278369176641441651504986605158220586834603467688335741155616241506048203605969931767808"
+ }
+ },
+ "02": {
+ "a": "1",
+ "b": "0",
+ "g": {
+ "x": "12945521200488607599028656523227600834645282385529945429027333942356897353457141653432411062448887162429396839725905",
+ "y": "28848503114551943942613290154239739502710619007562434518751494790901286961962988591861282401800949710517326509814280"
+ },
+ "n": "71314261946000873",
+ "p": "37392568050767930319799988287205396758117017539972057881598316494924185591542182483195697473804013824755052059608001",
+ "priv": "29126373822686368",
+ "pub": {
+ "x": "32203872504800826193860578257942098817761632037322936149898772567823772721868451723895290957871284796960470523979193",
+ "y": "29602813656567751793759332218082879597530452170215742929397002601119577441784146888237119786583675093403524212008308"
+ }
+ },
+ "03": {
+ "a": "1",
+ "b": "0",
+ "g": {
+ "x": "27994076808475229758326263133362929272220571606747122907327470869596018889793463129645972572266834489354416647381824",
+ "y": "25905505044642050008028336652499541922197718613122256210203673259353739613110582288166640021538525466499440893496683"
+ },
+ "n": "65153636961774397",
+ "p": "36344353935396613718356487407699793893725869238821772569108732609306670398289558080400955729328602471783395378286633",
+ "priv": "12823911728474639",
+ "pub": {
+ "x": "5989795792720183232357308397328552120890832370159249479102017870689050146843974909018077446828100022809937759037457",
+ "y": "4076499043434397184167747716536775685672659730989741811348214546850688174088048243849389563176846351391019790440130"
+ }
+ },
+ "04": {
+ "a": "1",
+ "b": "0",
+ "g": {
+ "x": "22606687668269298114625240207522873142726269014052537843427518017813300084818537975263731248330029611849165060179698",
+ "y": "22487350102024832247251097934408529105395697460802052344875349874950231881440810299529934247574539849802290200440206"
+ },
+ "n": "67537375118463713",
+ "p": "25066384285441205903273832649434882702712612496016407378135255151484493899841608613787340526409623217340548154752257",
+ "priv": "11635865700012297",
+ "pub": {
+ "x": "22021752605428965357178777617015527233578373960385071831838131873160197100814268130275797060808542178604912347883389",
+ "y": "23866939163753826944639218415544304773298439266931849491790315194143842918793955304612855324679875974365253172635470"
+ }
+ },
+ "05": {
+ "a": "1",
+ "b": "0",
+ "g": {
+ "x": "781819923528843818061353484618984968876099407238823837591984121830775798915631450542772051465612287365705364064998",
+ "y": "13219048869966217368618050570644487166158059065919396407529689500553101289292505577394593103284384706085687130679914"
+ },
+ "n": "50339060180106073",
+ "p": "20540151207176407610392811638129548448205144944910278982948996576713892299586270552571422734441315161712142945629849",
+ "priv": "40228399726161800",
+ "pub": {
+ "x": "5617828531306429109131542402145641940634218296626854652746172963700888272248450563965281635311417296472764855113753",
+ "y": "15121413581491496478205098277793818091231295981171324129530352426474092038164705306631251374991917540506560457042695"
+ }
+ },
+ "06": {
+ "a": "1",
+ "b": "0",
+ "g": {
+ "x": "20290983142717519792261408686352487989649211887922216833203504479698185603590002277493991836124831075173569580204477",
+ "y": "15613576728870816857160584481855675933338821085093804510572444643308874185251477239943066930147632556638070636441432"
+ },
+ "n": "36577089244984073",
+ "p": "37990732850765540949258158252123434514839333303742675794943500457245740454631544112729007639103771574156034280604393",
+ "priv": "16765165806610496",
+ "pub": {
+ "x": "29299800775213565057549529503711254775854333861363066212479678551229808304583729940632334835601591770453319125573966",
+ "y": "14861466094377865190522653191120791841827985989676034034282703670486520993005899046766857612407262012243607466617974"
+ }
+ },
+ "07": {
+ "a": "1",
+ "b": "0",
+ "g": {
+ "x": "3022230212861852143926252523215574239971355724885382805476990984159935367480775746448786270204099464042384143262546",
+ "y": "22692252008411764842293588588620353137409487094887514780285609890843172954491503687225347309851119975391662003184206"
+ },
+ "n": "42711093252530077",
+ "p": "34025505520977025383797421109353705207329755039923206461385189688570023154971691983118444196840659984974006014915457",
+ "priv": "28625914362170518",
+ "pub": {
+ "x": "9352001430116070356229866278421266037881922229432783428504987997385316307975037351847840858083283066347881190861984",
+ "y": "13660483978543810828797076254776611318256965559421711578116057132999910591236081024558566808003705887292790181522400"
+ }
+ },
+ "08": {
+ "a": "1",
+ "b": "0",
+ "g": {
+ "x": "20546520481953678154188673002497673317951351005548515253692962760894884550885667364279279675317349577557539360814123",
+ "y": "9690423372408868664356492113196121928041525311419829379643952572628949982787595259238649512191063658749129235349599"
+ },
+ "n": "57764213524659997",
+ "p": "37296045993145557762887615869529446066927464675046163533740890434147377036252939859599505430619316010543536008593953",
+ "priv": "42940447838889445",
+ "pub": {
+ "x": "24333724270092143621713826802597896628928936454919800951047900078926973110794950428837308243267285488795216606840974",
+ "y": "14020134285706927331676614030279900017291016148631271055361689697974801145765941432183225698727390866903667219687969"
+ }
+ },
+ "09": {
+ "a": "1",
+ "b": "0",
+ "g": {
+ "x": "17272533675023793624680016937607161394427776688401278127884215858369066406365237833207419170117031265147050748737186",
+ "y": "10897684556651576571671151674586120690608236542740270859915076272932083320838022698730208293779451126638581586588925"
+ },
+ "n": "44682719955829289",
+ "p": "31123778862031392435299439090755153401162704597024288571183830527113563344679315725116915983118187065183839828632113",
+ "priv": "30177475288172038",
+ "pub": {
+ "x": "10584120526089473026246191383792758367144927589909587205278073830223938861208553884400816982485323081066790399437204",
+ "y": "19710761542152200618172612283139324015316083022563473705358032993141026289202915973780473937312193485361804450068338"
+ }
+ },
+ "0A": {
+ "a": "1",
+ "b": "0",
+ "g": {
+ "x": "23948165163161423827781659252187464228156720755142058092673382257634334615418008758683925938170704019069504769068767",
+ "y": "29262124142683887534232736126380966649037190576572850117401576509403154245303113352176870318970330981025925802076215"
+ },
+ "n": "48764835656345441",
+ "p": "37184132387158636185823166107076967114138479407440093455278818158072422008561996049871236605258164895216434405941633",
+ "priv": "7983635268050735",
+ "pub": {
+ "x": "16148631041299144072435534784738008519949841221985024060408677162532254304915141767288991659528028804911680226440414",
+ "y": "11647588982042777999933885074728841323429055317640349743317690400085264609368266409172384083304384956740124856614996"
+ }
+ },
+ "0B": {
+ "a": "1",
+ "b": "0",
+ "g": {
+ "x": "17272533675023793624680016937607161394427776688401278127884215858369066406365237833207419170117031265147050748737186",
+ "y": "10897684556651576571671151674586120690608236542740270859915076272932083320838022698730208293779451126638581586588925"
+ },
+ "n": "44682719955829289",
+ "p": "31123778862031392435299439090755153401162704597024288571183830527113563344679315725116915983118187065183839828632113",
+ "priv": "30177475288172038",
+ "pub": {
+ "x": "10584120526089473026246191383792758367144927589909587205278073830223938861208553884400816982485323081066790399437204",
+ "y": "19710761542152200618172612283139324015316083022563473705358032993141026289202915973780473937312193485361804450068338"
+ }
+ },
+ "0C": {
+ "a": "1",
+ "b": "0",
+ "g": {
+ "x": "32366559100369318283806949847668006966372576295512713108321085041414300654732780440477281124875100457132910713385392",
+ "y": "36277066295525832825357611949223811038289235173317865340414967683326061355424351588874247387096082012795578150665609"
+ },
+ "n": "59338206178439857",
+ "p": "36883284215161242563310145090645358935159680728419347578246433941874667246014425073058641415639952085274328207007361",
+ "priv": "40581906428014757",
+ "pub": {
+ "x": "27897587677206802935272072179740121173143753076733201426736721660648622269207410244820576154042145772129856483317918",
+ "y": "13615609806169825354266127137741977194548952863339923138634202769645906429284217242635558548859194566413379013960503"
+ }
+ },
+ "0D": {
+ "a": "1",
+ "b": "0",
+ "g": {
+ "x": "6645465708298979297645218319744955265667580573078366866240130998337156417559279947807138605379710836345182353956566",
+ "y": "9122261325743960629676061760923709333528687205500940401556553622283598790250115820669732772373561034819836006012285"
+ },
+ "n": "54718482591717193",
+ "p": "21262683770905544338571543505453061536845396135304775106786244478927459953699178453429809049886663583535515332608417",
+ "priv": "47335405173668092",
+ "pub": {
+ "x": "17901813509704147483830835266370702882674023911261162322131513567769351494873007879644402037648391915282581963897955",
+ "y": "3627746470775852993311378053985025489205823505060996524650056711113522565534673713290725146394961076678997021207516"
+ }
+ },
+ "0E": {
+ "a": "1",
+ "b": "0",
+ "g": {
+ "x": "27747752307286592687012373511047845159334654229150694584737865727671140019146915126658619381536913889340121429777176",
+ "y": "3432951149395499007263552055243423973930620822599982913138822382764310200465584292869885640731380391181334006544903"
+ },
+ "n": "69347892008216533",
+ "p": "36347478437802048537119868924527781602382983008254976074874612889097641729112752259090095081683689659920202493703297",
+ "priv": "7092493664915888",
+ "pub": {
+ "x": "21652922522868334895657043827148412844567405193561740682190228631524297662741918392809167788290748819278548343887903",
+ "y": "3417364464298334389588552458831357703430726188539039648711355435080336809889862010595330876621524473130281045660871"
+ }
+ },
+ "0F": {
+ "a": "1",
+ "b": "0",
+ "g": {
+ "x": "31776059432192763776169381921670178722866221070834058273282940403000440589856847475502258046219835656769351443888388",
+ "y": "14915954572069018210816473452568747806301836720199982203742875487860683708009757250677784429672784879759557934677295"
+ },
+ "n": "60306638703816809",
+ "p": "37861187394286237954223210768267876485159987135721389001525364888539928951972506513033460251773122312456256755333769",
+ "priv": "43529410493479903",
+ "pub": {
+ "x": "36937113900362437545657429676722225709769818478521942542158699404492483695089143602302938076641123916321507892090940",
+ "y": "12300711937755714474221683340048792628817501853269187222732097530965245794898485391792926982501341822327927281168157"
+ }
+ },
+ "12": {
+ "a": "1",
+ "b": "0",
+ "g": {
+ "x": "11119482656822991700792578907460492227713548578133058475037279114658452606556520469737149880517581700365327698611081",
+ "y": "5312392362047363949252475376883941023428136467239031118254622461615317640729075312800894148424589785499630341506080"
+ },
+ "n": "61468465254706841",
+ "p": "20622394400536669015009109445778032002575716997347454488103759663466131824487696837925141032629668839547983981006673",
+ "priv": "60745091089001069",
+ "pub": {
+ "x": "8302386161994476463882352663800987677857025296941809689065347673056316489123420195107324646013409722355145362105695",
+ "y": "13363649414286723252942106921229466872616885916170044867152681460547108642096237962603450424133488992957379857797813"
+ }
+ },
+ "13": {
+ "a": "1",
+ "b": "0",
+ "g": {
+ "x": "27454888227856505533387855329956788267030560228130237843019128731561479441383843643211794715596006608164303047382767",
+ "y": "25734101585617196914691138807004701507679801292492905532148885152767040438129871790752711796217529957350537646074954"
+ },
+ "n": "38771992745198197",
+ "p": "32512713267117547802229004817342438100721689377119915617511876448957214358251584089752707605032440065201094448831881",
+ "priv": "15976728344674105",
+ "pub": {
+ "x": "3691704687927058819591076394169677514664333662183974274461082367921506972751896092475629328058011790588662903256832",
+ "y": "26484003440265260647575762004113995465586854417593253320671406420252567198975995448928227659791539037587765978967255"
+ }
+ },
+ "18": {
+ "a": "1",
+ "b": "0",
+ "g": {
+ "x": "6310475814662352568971560182310231839329343724408624519389068728320329025974637390988828335460419687090810096444671",
+ "y": "14975740609692212121466982863362652836149004779446935330110884359582284319436292141410425119946675031763769510936013"
+ },
+ "n": "54695987280141397",
+ "p": "20382341820853234423840825688329019101101189275426194204365984074203757959383616959383036631061239138112927267520089",
+ "priv": "34992317936760591",
+ "pub": {
+ "x": "8706389485534845673163734064079119714439476595416111663093903895319551340520311271066830871273781861930387023628095",
+ "y": "4443601879949176681910035950062822482896269563744604779691014779955561545862216697926657333283397354995534927843775"
+ }
+ },
+ "19": {
+ "a": "1",
+ "b": "0",
+ "g": {
+ "x": "7584514146265657723682589467472480210708798127771966639002925072279390565944732637329803708869161392955456901683208",
+ "y": "5764283675033599948981599061678875106928092179619498039027173635003240679699166287323607856795584908008068710374623"
+ },
+ "n": "45247533306073321",
+ "p": "29904458140618354476427451017550930593422131725263169701409831912303561396966291922475820357156233696613726793819113",
+ "priv": "29657152842312895",
+ "pub": {
+ "x": "17576167019544040155390616697334398449082456265796782458191155901005030032653815532964116263462127482133737258864700",
+ "y": "1125407055820070498649143362555264611724476175583265219055685553252038666319259789915739639733545886876232604191242"
+ }
+ },
+ "1C": {
+ "a": "1",
+ "b": "0",
+ "g": {
+ "x": "22855249491408577399314114410491415950517593355478182149672442878739161291712677791480806227311388739667949116186643",
+ "y": "10090748700447563344768464967976982814599035434371109678353441279762990928564733098705170129446589067321569664285856"
+ },
+ "n": "48327092680035149",
+ "p": "37198856165827359239624523956448360398873513822648810088561724187860467287854220885995282969477483102943902841369153",
+ "priv": "16619186003963700",
+ "pub": {
+ "x": "23301265649040637976531382749590463952316720099647572298097775954000521920517815910803570872646950167923329601997134",
+ "y": "28939329175037377801073962070204861485644082671743919066988639734312772338759696891645523206570996463742438828645000"
+ }
+ },
+ "1D": {
+ "a": "1",
+ "b": "0",
+ "g": {
+ "x": "21485907255093637178082315005177275537228742177931509431249056347300555552172888693235406942297454493676702531931655",
+ "y": "7637085415458452555331445043889178137700055152197196242022245472314658145011526482426816376681157002338341647989098"
+ },
+ "n": "71650264922603869",
+ "p": "27845658323610558342493324384410335947445989111503711636352684588775122083872122365066007826271926755322572707136313",
+ "priv": "26815466003754626",
+ "pub": {
+ "x": "4876696263453032445338210618537086689338971119926272787904035176296725481867195547017440481622297580256815541015926",
+ "y": "15853826468148827809563406431189387397493981509673040194341328851566636137415804518532176226406586339241644224217344"
+ }
+ },
+ "20": {
+ "a": "1",
+ "b": "0",
+ "g": {
+ "x": "6686321999622051178591311822099609521208473884691575834761183821695369178088927429575696614600592264838083653551328",
+ "y": "8708660980615804987290390922286202932010531171713457714232968437316481186496784893214865780968004644609012939569295"
+ },
+ "n": "57001816492288169",
+ "p": "29147266190978487142724331180857761358464152478756370901789788622663454507157070029841119463934333045189074823748017",
+ "priv": "24105224018429147",
+ "pub": {
+ "x": "3079838111989033565943043999904330598009631832293766291336987193469067925154485617252460140233911286520214631295235",
+ "y": "27466153539310732778202127946739473894168326873113036251235314475869642331462095667900277662828596833955915872259873"
+ }
+ },
+ "21": {
+ "a": "1",
+ "b": "0",
+ "g": {
+ "x": "7218781427120785178725623901975299305634810332201168561903403409664405857829655009079413595609453155845412233075193",
+ "y": "19449453204585732846377914924665821314567408072899635427679464303538225464188449754928687947160116118731610122451971"
+ },
+ "n": "70641998984652317",
+ "p": "32354709286228852182518787575716369018376048992530369544020867305267989998685044938366506455565414707817181388680633",
+ "priv": "38341712192133441",
+ "pub": {
+ "x": "14023824446142707343565167755394444040059760284563816029377229622588770661846541780333029942315327565958606208771106",
+ "y": "30604751698189796066091989007727114877131638436543785875345552646965733337783659422892989188358702333653008106463265"
+ }
+ },
+ "22": {
+ "a": "1",
+ "b": "0",
+ "g": {
+ "x": "12259358487924366608305813282440364085684395756994923636191629847503895994037183295786380452071239418106026509150804",
+ "y": "14853676372788121804436447106529209167572424731944959299344702242030301728072117127341066233856180747847416655851934"
+ },
+ "n": "69284057899286401",
+ "p": "31648573662208007208411279340972174081655191771220726603117102285639562723584318781472781870749438532939445789762497",
+ "priv": "13576107630579530",
+ "pub": {
+ "x": "5871898692465293699950936882527671235864759453647136933264801904900692020319864572178035453433020771524967155028662",
+ "y": "7797169826989892215278245730061461386927964876868463824394796499325209401088175936040551790551876059967923119137155"
+ }
+ },
+ "23": {
+ "a": "1",
+ "b": "0",
+ "g": {
+ "x": "18986140368912686946766824672798319264943410511951605590295624458023663413315771550412808116691709592493884174247323",
+ "y": "35582835919011558986825813010572858416130195540793539052310817770750293516630582064601225899492793739318461290416459"
+ },
+ "n": "49636728679305421",
+ "p": "36972713617917281884750914540945557203256304584341577847131541606985792593160647528404736364994609090002393518365297",
+ "priv": "7621238846312565",
+ "pub": {
+ "x": "5474861534966667085906840131133038788933705655580507041430931765582606146380837172308924465130409686699600787594543",
+ "y": "11326043172398492374226759220878127907308526789869115594345877455697735198293097656639000464933130127615502362106702"
+ }
+ },
+ "24": {
+ "a": "1",
+ "b": "0",
+ "g": {
+ "x": "4492318878195287028641969069300774407040103059932532535110576316170354692927817610666693376859152036186857275361391",
+ "y": "1694746079656212098005835261250868391807480551771588137885173193876219104438889416288917386204684992492306399883336"
+ },
+ "n": "51239258040959909",
+ "p": "23971312951249835125727253564197976328111252475442288537785054438561546287783425046926796895043478372563040474056649",
+ "priv": "1184680163675018",
+ "pub": {
+ "x": "7469701811829692791542904030466988831653197363045152552888543494171712537634067299840014762722678773980197367532093",
+ "y": "21442244090949131497466966127353491267322103670986664241259520242511672755523936797064703693562596797394045432190546"
+ }
+ },
+ "25": {
+ "a": "1",
+ "b": "0",
+ "g": {
+ "x": "11926898248241239748997351957173960056057407886149788887758062574272894012644073661378923746287542171374583361479761",
+ "y": "35419490850545970758577819248219444638250772547354989411487568475288779473681482073873703451548747635418769420793286"
+ },
+ "n": "65954858530398437",
+ "p": "38505005783574214474412480744393764780948137723283702040743108245361618646062618204011087438273094275540438104519273",
+ "priv": "26941797169371159",
+ "pub": {
+ "x": "35533456553226765761636011384686492624398611798034646981562720601482557741905776634955456778290492506576434423681065",
+ "y": "31327464208115609033515355290240501419723636369785092263794133094830273012773664815395736769013183396740555644058707"
+ }
+ },
+ "28": {
+ "a": "1",
+ "b": "0",
+ "g": {
+ "x": "6625455131255616498288897401740387586936919298398630888817069955271802346063065950505620943020700795501030354951483",
+ "y": "25533652931145206810096025009180082955369059200957488574448993391838671019475012100931337253442582998280032435349351"
+ },
+ "n": "57483349306202381",
+ "p": "31180364593374161260541214644085545950368042282359256671297134949278949227610474415915698419926523326596302438006769",
+ "priv": "13136214442180721",
+ "pub": {
+ "x": "5104925930512638672819053368212255937573137611150786858226532094853360078971757032168938988793670627337813923036767",
+ "y": "28137487828227178563350402753881014405678533666094621586427542674382206038438535788143080548493760349515756182012498"
+ }
+ },
+ "29": {
+ "a": "1",
+ "b": "0",
+ "g": {
+ "x": "6855965928974656223860567398557704088817997034038651863138515626385009760954658000974356371150696139484451845926600",
+ "y": "1801238159270279246169147737509397655357290457453559970603838885439270588090298720450362006989715720109206491245093"
+ },
+ "n": "67647193402298473",
+ "p": "20943044253804132319169216830228672625270249954489249987858922604701634645918538145031729465712318342252126112985153",
+ "priv": "58908212650039669",
+ "pub": {
+ "x": "19589519046601397260809955269083626795503130334091451763896601804243999018446108131405408867157069655563420193230043",
+ "y": "979397535273986461157952793344176191317009812589408140414741804758681355998002007487306586139600254357725560998472"
+ }
+ },
+ "2A": {
+ "a": "1",
+ "b": "0",
+ "g": {
+ "x": "6491087841214587051264545986557683007600933910896314457162076997479104680607524492579346483250057819719574751118546",
+ "y": "28889674849416975039297975655960492533273983902836344528214812450760488908413247697351485992563586277899237970177501"
+ },
+ "n": "55490915388926201",
+ "p": "30609238151955025112052355607151891160055473451727463357136290171496228014314319402618394255507642663056173045397961",
+ "priv": "28356164640468958",
+ "pub": {
+ "x": "7429934306150060362220520167219696196103387398223657500784703159452793671818880169418653109022945805967279598841058",
+ "y": "16695949431099551936765494864197903910720045366223287633678257137673564581472696006269235457344268044769517631487706"
+ }
+ },
+ "2B": {
+ "a": "1",
+ "b": "0",
+ "g": {
+ "x": "8915903858502646066418182633057705652008082145832256923615728473200101206132031281584883906271118970991755030551416",
+ "y": "20464678754304824937079694961279040773502428396767671213114450862571235656842986110419159780072381959022618240357492"
+ },
+ "n": "52255053939691037",
+ "p": "23565722542837335065074829499441916969523862484272548221564258250579409483831082603756318140516261012072179955607649",
+ "priv": "49376872296925867",
+ "pub": {
+ "x": "5208399005152010558700017443262304096033307781594722582754654119839186077071380964884760370919282614223655552449192",
+ "y": "22357703575020535444907398820227602869440920600838658819039554416206966784231890678810435029947588971910074121002504"
+ }
+ },
+ "2C": {
+ "a": "1",
+ "b": "0",
+ "g": {
+ "x": "21673361717619259910600499419800485528178801849923454062050055236231939594233283543796077751210469045350919066368895",
+ "y": "5232476492611604888729825305639232005017822876108144652169892952989580351454246958886421453535493897842819359154864"
+ },
+ "n": "55681564377333977",
+ "p": "24412280675538104642884792561502783185577987209710041026341163083973933860854736635268965257725055809364646140091249",
+ "priv": "30951839223306173",
+ "pub": {
+ "x": "21551722775458524408480112576069559265917312687549112053580919391285918530584174752292844347621326558272739603979057",
+ "y": "13463977158522661542654520438933687107907187215503371589980428235633526671841388652148099285621876350916055100879930"
+ }
+ },
+ "2D": {
+ "a": "1",
+ "b": "0",
+ "g": {
+ "x": "27781912721787993763805837568064263711340931435239060864256539635990160352746069412406130189835503935411239757870741",
+ "y": "27364922370114990533080625336285288934681289975914886077419119101693257916498416164024544331981480303244517347734251"
+ },
+ "n": "46591021859161649",
+ "p": "34434335923751399698518505516722285557281631663360135021571830978812886664047949565106992641249608613800031755822209",
+ "priv": "11012852810209962",
+ "pub": {
+ "x": "4799183354431172708437474398228298037089681042678881469855476704311534306845199897373322889867450051628647190714371",
+ "y": "14871217001746100747746722676908590963712532469411562675056088017233265734517784273850861476487467117022794466227739"
+ }
+ },
+ "2E": {
+ "a": "1",
+ "b": "0",
+ "g": {
+ "x": "10910744922206512781156913169071750153028386884676208947062808346072531411270489432930252839559606812441712224597826",
+ "y": "19170993669917204517491618000619818679152109690172641868349612889930480365274675096509477191800826190959228181870174"
+ },
+ "n": "61760995553426173",
+ "p": "22604814143135632990679956684344311209819952803216271952472204855524756275151440456421260165232069708317717961315241",
+ "priv": "37454031876727861",
+ "pub": {
+ "x": "14399230353963643339712940015954061581064239835926823517419716769613937039346822269422480779920783799484349086780408",
+ "y": "5484731395987446993229594927733430043632089703338918322171291299699820472711849119800714736923107362018017833200634"
+ }
+ },
+ "2F": {
+ "a": "1",
+ "b": "0",
+ "g": {
+ "x": "25904051482675514500669093529301214170223884490017250779967799045498125858161801278923249219988634101342134538786052",
+ "y": "17368622637199623459370355450886727695380052458605518871156173742379499927409697901891660320010128728180182665357867"
+ },
+ "n": "62443961168019161",
+ "p": "27407396338439569164955230033365569790027808547807104696365020660004821507019814717465116357974159702372050777059873",
+ "priv": "29662783944176267",
+ "pub": {
+ "x": "10041352286586128940778441134697140947437132522963541282603223909964089228202203447893168630967079559592385624545192",
+ "y": "9292360790888709163192008500642345429180999836863864477254342335185874973743595440806854122467192796977299364198680"
+ }
+ },
+ "30": {
+ "a": "1",
+ "b": "0",
+ "g": {
+ "x": "31574409824570705964544367030368440543791401849426544831850080936306689199101549482866255489086770161031315565401331",
+ "y": "2822872309792998318093862348825391297607820893228186010000901024593413215493811572635496939163111762266343070301811"
+ },
+ "n": "48959934415612973",
+ "p": "32009921376317960221576065562805166480546341594240230869485042707378974118124593731053232945497329129143547457317801",
+ "priv": "45906145109462193",
+ "pub": {
+ "x": "25897134114588480425265684642921204121884326347274237065932995903818740612744847914045450349302340709998384364312297",
+ "y": "1605304482344202101863265512591091746499168916267043520577629617693396956565214733104594178622005304907093890699566"
+ }
+ },
+ "31": {
+ "a": "1",
+ "b": "0",
+ "g": {
+ "x": "11188104450577873458911701429695026887774021239954257546409604848401278693592131834788763813758435930816382003958104",
+ "y": "24490951733272171720884693434505468532109494775176376686967265901204761001801843130321166548162318419048087471035800"
+ },
+ "n": "66874636907653541",
+ "p": "25481707350880489563331220397252197864427149004368996522335270121024731904125866347924725777243159725371357561236729",
+ "priv": "52925767743678469",
+ "pub": {
+ "x": "1667247963417966237212807096289668964696884414761513558217414317572656739670183406633077067724180311299088421164173",
+ "y": "16748564218264747164349322762189378329328804080520961090155095866935688174130443939169605936102924753154349010438361"
+ }
+ },
+ "32": {
+ "a": "1",
+ "b": "0",
+ "g": {
+ "x": "12726461294499926560068151670755648381327270933570408046980855499993821725946986709210217963523130634525797609551100",
+ "y": "19727466362747241639614430182283134406657859985308135285523481410218197736089464247591813328077488945200498871246573"
+ },
+ "n": "65794461159063457",
+ "p": "21055788153165092719902120162764441840863916414168155711589396355396184787671893056148679610453574714946317283911601",
+ "priv": "36261933107303189",
+ "pub": {
+ "x": "20951918253348273252420340105342001337430637214876028091851180291652873950025505424806224449373381285608077226552471",
+ "y": "9574918363679101910324218403815091089131481132701762206865487974994855351639447295943340460718678168318117194195752"
+ }
+ },
+ "33": {
+ "a": "1",
+ "b": "0",
+ "g": {
+ "x": "1794865730835385436163427753723234719911851797686636255721756602521630801773080869578590362010786910928772822065072",
+ "y": "30644486003529828103888328722673972171730735334350555137971150233266085818806168194592552532099145733381090086026739"
+ },
+ "n": "39030245206593181",
+ "p": "32570677563636890576365869186469870364879811420628282404959348810134494363087895710691433232743794272463480085754961",
+ "priv": "34481221421628229",
+ "pub": {
+ "x": "907296736569259468480041782855281364952562359519792244665824534285751872123373034165077452334975888459663148242736",
+ "y": "16927761660112078837951464089861279221188811999337390492625539371026015626584250804363204864186060157462161862017016"
+ }
+ },
+ "40": {
+ "a": "1",
+ "b": "0",
+ "g": {
+ "x": "4059949146365219555765942623881117805902135583342215173483403715338700834444334843734013438929948804356102673557995327491778895286621343661027886194229423",
+ "y": "2666176389066415236284652473344297039725375670348031203453175504900403049498614310424697925683808910311136608699171612232668547550268382836372320506920106"
+ },
+ "n": "5433982808887507657",
+ "p": "8593089364081001067462414866654031030011369860377686076521185730682021902004001446804904031667686514463236003668466017626568697473954285995216040950902881",
+ "priv": "449278429561237525",
+ "pub": {
+ "x": "7559615723586709586458106004507017059372166711271777511283228857051909257718309123926479472096584643986638698351587465542509690715985335205369481790178546",
+ "y": "7080073383749624161526624872543179425900008718862030231798273629479785989924538511939628398505421596500162321954578945975993952938126069166218024480096454"
+ }
+ },
+ "41": {
+ "a": "1",
+ "b": "0",
+ "g": {
+ "x": "9791458979524371820932506373340791347147485287286801025025747008476002029861528741424050864358137516255664108423493779065350932029808518858376062167004536",
+ "y": "9932434466111647561557538581748799870403761251980691823240328064662070366553827221038647353473056891319938111493174855021955908965618290167703383083703662"
+ },
+ "n": "4927638009777311293",
+ "p": "10165754444795254057389422393400930472583053728543041642319024171930216155078184719345890697917311487018908539453332431395199632756711975301609704092843793",
+ "priv": "3476326144393184330",
+ "pub": {
+ "x": "4462922298422522788711301077640671149487080987386610884077317356313747587278274922553055511229554308642911107087728929458238030390328053305039156712425692",
+ "y": "4166331361209663080277908775030002767045551689443380649904104094047767422069625957190676222747168197864341871814070164924686453916110248521040648287862677"
+ }
+ },
+ "50": {
+ "a": "1",
+ "b": "0",
+ "g": {
+ "x": "3526841193795042475472706746149302104479319317991814716511154371943217402619533559013289199455018742151609469798530459011064934359290058269305005770852147",
+ "y": "6717176849269195704898319671657351738994934261460853058693785103888428006927584989649644563176787348070595227750218564079606740227129140124956981993714338"
+ },
+ "n": "4807115327383806869",
+ "p": "11685037692629544436418522744508054167282745075683333963951114538336503311896091970659888174669185217769701714376736146487719134933981559784973709552957801",
+ "priv": "4040249819685480161",
+ "pub": {
+ "x": "1466527626291203642492493441827733692299414093298124725156614801731872416353976088094297810392380176144498426351645671333471717057206065528475943181211237",
+ "y": "6552417402671779327103814822554640695446837969767667482775077050206682335288863224018601262504683488603938304696807511771370029474264413197914158855338659"
+ }
+ },
+ "51": {
+ "a": "1",
+ "b": "0",
+ "g": {
+ "x": "3267199711920916068382989896497476773626172933101820659737975395054177436610723611881044090850152653690217799193954704381970206244579237161200895449914309",
+ "y": "1801172663046216945616504560716718964873245692895029091693186427056304450272172483757301760952623806485351084272296014098491704676025054216449233661159465"
+ },
+ "n": "4951776012238716889",
+ "p": "11971564937725142819283405343102452394219517439200754177998125173838273140006904866009097341514436842653399766350815005672865218078609842575520666728570201",
+ "priv": "2697332072748954056",
+ "pub": {
+ "x": "8029055570922781997068925861526172224421716783639627816091029975112069739370649863950940149054934973985391614557927450496740677679026308718830752438909007",
+ "y": "1602626801939716053837744749626887002577837581116068515054873921829954905161054352599862173139179466561314851772116951576800443217651935171703906272161567"
+ }
+ },
+ "52": {
+ "a": "1",
+ "b": "0",
+ "g": {
+ "x": "7622412265904735790820724331145536880745869825302538676187160201387756396703356170295759091096405122096528698138948171749042031919696117032628083107811310",
+ "y": "3538375182189891751042048643308526629143293454794797073670319319588710166560996649992384714763805806154167398467726209193990040912148556093458840915181768"
+ },
+ "n": "5216282502541235641",
+ "p": "7925879388779818270822108768038895267533535400819446253716123243519501003959374444666474060360457012670942180897278261140356687371434584564816524729756569",
+ "priv": "4227382804860771752",
+ "pub": {
+ "x": "6623556837430211176716056285998438105129944636206613041325109163453346309568154499263565700497812782312007627435399691032717221155535887685349983547725754",
+ "y": "5143784137008935243415940746877546954904928787927831202191636787181715337470635194144636469817455076012295951914913996004499369538889959671269557189749708"
+ }
+ },
+ "53": {
+ "a": "1",
+ "b": "0",
+ "g": {
+ "x": "9952482702654268996410178765652497590105592800065574407952582838585534879676909122255372769768497901699832734933374032257806046204765452502338245789575378",
+ "y": "2089340264888419262996854021383298637761210445052455642799587750065248165559506120835367654357551061138377729286193320086948280413270555247250470924892526"
+ },
+ "n": "5068632114228449537",
+ "p": "11157014936597533577019045418547240616925175420814360521608554171517236939326924856555251208920173226882496853458122801623011764787655866100297968178218817",
+ "priv": "190541113341533176",
+ "pub": {
+ "x": "2564907221347665920571154160633426030926627289520132946090180496419693396052978749696275133983838854756474194181054881535849242976180540032615757743858664",
+ "y": "11135232968162438329449039042851302679976903318047276891184960732245822185866013956710495287987401311857788873227422869430044705095334454666338599981024663"
+ }
+ },
+ "54": {
+ "a": "1",
+ "b": "0",
+ "g": {
+ "x": "8059057663701168311917532277618827622978515614146963913097592614451721430413021070395782723330339842826599481063797559797462512297834269467666807971588275",
+ "y": "12239303830174753191779705979220378623394732267536997115625979632402312087683644927405756146495100825573682155171145924668759419114616275413724686284123408"
+ },
+ "n": "5622613991231344109",
+ "p": "12509642519697332596114311053544618620747009389814652225369521188710171926174976419995384745134703589248167610052719613586668754176591418831031596093374569",
+ "priv": "1285511085175426271",
+ "pub": {
+ "x": "4895832170509729140211911021638266775170167022247175324972987673313207244495397975379010973250279668424167408883454560376269866102669741515127286188717976",
+ "y": "5846013328426281815512452704859777850382010968846722453046994319336479079120767834777937190955827245502389471872759584209649693396095099112777776298051208"
+ }
+ },
+ "55": {
+ "a": "1",
+ "b": "0",
+ "g": {
+ "x": "6137653643168830977493573210341261465614717541921335765523372705609926302508920096270972687072207085694032599882927761142125488149401308120243169594511831",
+ "y": "1116692611626831133742848724362766578952477258876677112469932772196188227734342324552510753173867142780554261113662225363186253941732748039097098530448548"
+ },
+ "n": "5444298836290678541",
+ "p": "10473306979012881681599188179078055086202328584566380482326833033628842931201028832804536290696826411363117488736195190074394651481452738323121603833156393",
+ "priv": "1269736890689062509",
+ "pub": {
+ "x": "4650623170875348523909607503639087653206390152378362042092258123447605461422798509945586046401058248503903342542527529157200711973543052628162388803719398",
+ "y": "10209840516991854949532155766444249093210770154167393071821363853671352167675606988017873164695500762694003816658318382717995295698876071542519382319020114"
+ }
+ },
+ "56": {
+ "a": "1",
+ "b": "0",
+ "g": {
+ "x": "4960509721617945458368580642866379390847536765961244922015383420768869132040210857829564768752090908952758141412640500615309020011921449898795150440454796",
+ "y": "6595393361357022586831971492865283914342750798336886829280323806253981918924718005172662662919610648909340269043560986140467143959921319064176595716361953"
+ },
+ "n": "5333056788847795741",
+ "p": "10131932795474437184505182928744955517005086247201546618805324424467046107439626954231777165370159951509101835472273379651227025599794671329418251258101177",
+ "priv": "4434249883815855329",
+ "pub": {
+ "x": "1172770485180406289548438805489238172938652458752801449695182972933434007863981252403269566933414708278679500279281603984809027281250560419216232488166837",
+ "y": "2561988328479962443364330380985679276129147386565252171129571526691430613594881953076301762095577025575119091407014535610035223707698926746396065558904243"
+ }
+ },
+ "57": {
+ "a": "1",
+ "b": "0",
+ "g": {
+ "x": "11541681997138096947059640626217256335590010810015558957838660670384501046708958294153446537000814645116210425008185588458637119407531965013915606791038597",
+ "y": "6005368336897383946053712133547710077829544935400386694181822584125711921969692732827743950232469716934494993598230897850139950250192220599418378965235256"
+ },
+ "n": "5399439303627927989",
+ "p": "12102796718467692453393852465930884217844007320684812308884617565201361577388880939207166958041434281709858488170378000563611988660191912455690313966830713",
+ "priv": "3340382106648491124",
+ "pub": {
+ "x": "11217839428734439950250846502958285418796433074755015191025889840499179348300718532677999032425018956425097909824357545605039703229610248933943518855035381",
+ "y": "12045087024656444440025664129912564518274343657610388544448667822205267635282339158360860157892456851041737779849075210151838188206611223153390103433592663"
+ }
+ },
+ "58": {
+ "a": "1",
+ "b": "0",
+ "g": {
+ "x": "8742479617325365073355572723061403277705878162662090085419647857915432034380838884182331045627427771471661809818973217557626908626797243120105686889125887",
+ "y": "4235951710044065849027617251773612939317435651015789506741050253822884117093183010776485855057169964517447282572222470621911735555961845433658291584164463"
+ },
+ "n": "5632003721094665569",
+ "p": "9794454636358384240729895767279977229411020075953528253025660757706495888891542340141549687900056461171671162700846411279434700622389478268943659614689001",
+ "priv": "4569149016723904366",
+ "pub": {
+ "x": "861387136531853706537023734435981260159262410289774525420990873996987761730100044660206239430883455266388013756147063972578354965346307128057844416149200",
+ "y": "7006975557159329326301638217355249420579171811475090662347327881973009565148150044573008668075655637434737840171901021724381960376666293775087295388354880"
+ }
+ },
+ "59": {
+ "a": "1",
+ "b": "0",
+ "g": {
+ "x": "1417663295731126013909990880111775495435125111962536211264999815422597907850488587287793516589211844302299750292063269100350848366980318854013463075751378",
+ "y": "935248870941618189769759304588309714371580820510747066022529761211554467706919006457613365052383069887808165157692794593847449611638544294811063776773382"
+ },
+ "n": "5086902831860639641",
+ "p": "8587416972080439597425167287409941311633017835994180185338278272235877764956176312565471862127626538620260312442279353344585250964695020388211173631645601",
+ "priv": "940892107441227231",
+ "pub": {
+ "x": "3770883299109421757733272865094182741004210105753514356630891710708138803345092633429903953978023199657510055248381198176379339445968801566102784221151673",
+ "y": "2743718531534495353553394212022116390060244446562081283155315109219186360933136452397969294839568512107603607659541951259553946359620734065504870586958773"
+ }
+ },
+ "5A": {
+ "a": "1",
+ "b": "0",
+ "g": {
+ "x": "7001153264502603531568809091006890066238093206490706740054133060198019760090859987689015805782317128823647585142349315457499198272662472818714043462452903",
+ "y": "5379780378477219053711555876878459214243674711784518156355184015695786277532464885846858297098947964642836892714492422913471742703229817151186461774623684"
+ },
+ "n": "5532044755580494717",
+ "p": "10562920556476600174223203553624763158759224241690200395609486946570543757980521851146458516500451409335864053457189473296570712977858859585999979839497081",
+ "priv": "2739897280441110808",
+ "pub": {
+ "x": "7581054250900465100241221249174490036171686256743764922844514529943814922537182958165791392786846977936233032863941877071806567396668766127251287523822606",
+ "y": "5631831699091940711241625425017356833183657380411816572111689187965538416134562629982530928101557014697032032310481274355673900378431834102530761513288622"
+ }
+ },
+ "5B": {
+ "a": "1",
+ "b": "0",
+ "g": {
+ "x": "1158043681401850645625830922140272354187157644535098167256945413239268444756596404093980140597684812224718936498179974083785242935482636867615430907732743",
+ "y": "2935477974787981099457948141594849481501751203602641415314751811824686325001189713561611058862042518908337169145979490701235192442660449822820835501173361"
+ },
+ "n": "4755964586330124773",
+ "p": "8786359934102436514978633891417766562160259052658042986450624118174984340932692337605038359551515406656318478331505297030190099751606005463323705066383041",
+ "priv": "174180799641457829",
+ "pub": {
+ "x": "3598207233336049755728485345402267878548216656271945302547031834697509569776838327330257694878049026614613051734265251666816782052063705326654727444817062",
+ "y": "2046662222697320726880876892159943082141709985523330392915545357354983340067789200377920213063865545819123049344758385363747768261733207129824387682384210"
+ }
+ },
+ "64": {
+ "a": "1",
+ "b": "0",
+ "g": {
+ "x": "6836914148383934523146386368854061694482882241590572738072281748520254317069250149078544973771604009318755611825773273277880011366390637667689995875645091",
+ "y": "1869210086814446552295647709671922572129135014994039637664273303812520716058868595903455367090271437468416294440316278321798763366666170148258617435501026"
+ },
+ "n": "4710798293276956193",
+ "p": "11140292070079840223478293553825852579756307272457526758455407348073991859638132039548754407195116517701496420375917235366272153337274234749677181046479241",
+ "priv": "11731326262766101",
+ "pub": {
+ "x": "1989960177638374390878377737764297057685259206834686428253479199374616869742150776410973898745805799780071536831208959469038333664656928533078897351495263",
+ "y": "8459798924827836228274277115421121276552682139164077587322715687363649243379655204356110674973206099056049071356775561545965708750027069182848722760722623"
+ }
+ },
+ "65": {
+ "a": "1",
+ "b": "0",
+ "g": {
+ "x": "3184985093531815189317401154768914988172000526379795240743456474818808085243678222504237337033350058066494144434504516171465736405092312932621770172533416",
+ "y": "6559725745443744013022481558427427919849356820887924942341545986134010594115539133944463128758999861888489753226817866803330838230286140442843910395787000"
+ },
+ "n": "5152953887135671777",
+ "p": "8746268412104364122590401256189368799957614918213941010980730641301654439417858210084651300822541590941125736513089898460381962115196275652326003031278753",
+ "priv": "1583498175279647618",
+ "pub": {
+ "x": "1352684437800180652923489312266978423036610385565765573158589347735420725101578006349602521095214805062717085612934589919983819276662150493306485984087932",
+ "y": "3751555619099816469086075504660083932492953973123328559493047041891340985823410815291323694826579254584425441385194091897267373260401958534526116601202095"
+ }
+ },
+ "66": {
+ "a": "1",
+ "b": "0",
+ "g": {
+ "x": "4248750365494621170867411070192250347558099282208077123309800561812392890309089650248112667099674539292841781223825841114353470559078798216015628807800405",
+ "y": "2363135147862625100780290668425392162931578480024321108046638130495288318114859598161763977525672580224389087872093793892799021710732333336562239007404331"
+ },
+ "n": "5470028972637037037",
+ "p": "7414450614060932787248839197458070896684910960804177158392134961003575366268790629245141903395927609515264078025359653122837316120017343739991702588044217",
+ "priv": "822304248535969741",
+ "pub": {
+ "x": "2533341772295393491400808023462145665845043632064869971512603543404657302513574864471005505089780300953060578102587786092252155788924277962864392102891310",
+ "y": "2853142146312045946205021435741931506513454835730828192678723851241580545655918715491324159683420265904946172614320824838207026955146237265100158801292103"
+ }
+ },
+ "67": {
+ "a": "1",
+ "b": "0",
+ "g": {
+ "x": "7273571546843413099993191994471155206649636421268389195048812757571665656628711965470673099293494650775090608549703675296316887753017258939382696588767431",
+ "y": "3529068830277582088596828423990199939817342479929127252014627303069162247307070606247527579307935679046819531543049464667736359244475241042487530444236684"
+ },
+ "n": "5092684937889775537",
+ "p": "8245498483844445086274997696534494324318871629323439587180432555305925857658196874670618312457436840885370130522487176480691396150486059031119600012524801",
+ "priv": "219689077615411230",
+ "pub": {
+ "x": "4722272800064252767454697391320635537092623053473493936821919057777751250795528775893773028180225310055317957128183947713166125210509990475635070787240674",
+ "y": "1531615552769437372403026851115800774961251901795490190286680044124146107960174759313522242631208697837075037127449543341158979848323485793132900943144563"
+ }
+ },
+ "68": {
+ "a": "1",
+ "b": "0",
+ "g": {
+ "x": "5314815905585889296798694589942539626853861931198694818603038996528084849226860592659970116239143301533686664128842093994835269693920687751688904127888779",
+ "y": "10414790044180029072298701038447244079242758942849978521692070049764442685692432822170776283556203601227171463278884193414648621672635573015724449767555202"
+ },
+ "n": "5725875683522971721",
+ "p": "12826772525868542995993863552630880658950068926652633231964092210337092764237251131994848166209877304480048932720132480186262823567355089380901269920285577",
+ "priv": "1068281577452339154",
+ "pub": {
+ "x": "12033418992548426346178523393578748081768559116860151229166249264538780301962627440762898922271298713141461639555947553862212449547395648972547457272406904",
+ "y": "4032882174174859318365824908716254483866659322383072417928411611598186762680107569672924388718908325415355049452875792560066378636581873850483566463440639"
+ }
+ },
+ "69": {
+ "a": "1",
+ "b": "0",
+ "g": {
+ "x": "7173096084863451615574458983860544861871291843691257280899194149874765254047059142205262441857301868057882685920836271904169877920201774602904928493082466",
+ "y": "3685411334779977585663385448619770855951447093889245910985895498674988632379639227046444801656846750232784910161110782562016802517178353986707750695901040"
+ },
+ "n": "5293859400497927137",
+ "p": "8380779820034448265154966159054835477696357572828327273565364892590557383123266250688404613890842142510687380806967918444847122708322525769781340041557697",
+ "priv": "4697401303693971213",
+ "pub": {
+ "x": "7654344525783880004912076071251050310876900359019139489057007158425701076455194924956926865732209623315247611882280988142426301468375261779854585638959095",
+ "y": "2205301557007321522756388509630157773456414780456128615321524979273286030768187976057798339743808057683824812565389382337153729181012589332286276647781278"
+ }
+ },
+ "6A": {
+ "a": "1",
+ "b": "0",
+ "g": {
+ "x": "2744957132896381114963945891295215205203728671990014493925705047714121178217838853986058119398256240023016028334778647494011445381032260909481773595313104",
+ "y": "9242294195628493222617132679668272569113830601983068223311165579910885820963605132189116485762422714509194310323531771573215902015458871867031718940322344"
+ },
+ "n": "4995269645533546733",
+ "p": "9569004333820764429459736949042280192002465065550168669273101643623459218410127778464060806179272357200390786174505285650425094011167595140853477499705177",
+ "priv": "4930017689226852173",
+ "pub": {
+ "x": "6042785424053265014481463288895667418403822173143764604162744788488127048207530937717313691222743805388834807415369489831117511798799943397780120043080908",
+ "y": "8129822965024161524487640831481569019315716746596951562838078884933023842144211446024042763464925599297764137258130591164153784795671822215714895806126168"
+ }
+ },
+ "6B": {
+ "a": "1",
+ "b": "0",
+ "g": {
+ "x": "4771924757248908953392581157041419562561060722669620884301556722064119360748361829387460466124743194153082874058153191937600246773960768487475418732779735",
+ "y": "1921088418563710749755929251575116022515200070039168455631128090489988043052648808257919406392722204985860080786583613334755486454530724103143500609853540"
+ },
+ "n": "5620476801810334777",
+ "p": "9200460722050362824128880874816963846428402133419587821922476691953499459138143260210705158151240733355428926202827167169183937677184899240672757880666481",
+ "priv": "3057923709521373326",
+ "pub": {
+ "x": "795969145680176830672700542020303991843545662981440678625855632938066599249164534703534071679426766547821556534491022316762303140598446657621887094211373",
+ "y": "6398709334040441212263545262049174071760680380022912073125188594335767745140265265998221067666818011052441785423830100964850376745023039032296345317686072"
+ }
+ },
+ "6C": {
+ "a": "1",
+ "b": "0",
+ "g": {
+ "x": "3193924578749149973349715439708853249371533674866738373146929732320027236261541739595179638552708548249437080416228471131201918968064263764697554111530165",
+ "y": "4888965687615736901315989550371141796747021791887255081237624800145952769028792494595799455118213679617455373330584340380954501271445892269198650215048525"
+ },
+ "n": "5716362938854350473",
+ "p": "6772644826114336975395521564093976272857924418773374298215345596476892260493496637686700145278269579146144605357425079537260056407908058166728104826706641",
+ "priv": "2077245658215532950",
+ "pub": {
+ "x": "268695446123955264077019637228932681884538989037732941099747311674045562360739358379871180345850032196900336613323005578507597779076899979732110092466639",
+ "y": "679259663772569453698820219709022062154214038591908789527736008819910024904428464410413122647073108532832895523045487629004791793096766249438993506680831"
+ }
+ },
+ "6D": {
+ "a": "1",
+ "b": "0",
+ "g": {
+ "x": "3298099620604059787834899492662174917598027267355370357344802081588599421345170581026563084037203023916968294761623560693756892912943381721305999449177880",
+ "y": "660070182381517254140291291235766825707865896406148611965367756543311281179754720142572450841218027728395896039015649326406436127710908614699312486011632"
+ },
+ "n": "4729400334442529957",
+ "p": "10949181517511926903567022348751201958461013848233333337252284131793670496593568885605542253013440341224349881301674089289841680074611115257051662616691737",
+ "priv": "1917167729222184576",
+ "pub": {
+ "x": "6148303559806694802720175134063952680971862197161214387714553406366855716527344657113993997849223962074971349265039287455185887671146559993479377577325902",
+ "y": "4457002224085552970249907174802329661250245161967874670366390075435589489905320422633893787965164168305287264752277411705970075802880020100425352544173375"
+ }
+ },
+ "6E": {
+ "a": "1",
+ "b": "0",
+ "g": {
+ "x": "6293451262500559701813798043459260113430548053466045470854903125080057224919401031898266214307842807651009391720013648728979854789012991495464126126839422",
+ "y": "5836148613114464303352123889645136044752294410204542326732877451461536676115565327431869868290307347722144018551412081044468151899437337237630579635928057"
+ },
+ "n": "4984104923219751073",
+ "p": "7383829322181609420717643550498284301822762121957563996751494118335844678856686816650259340126344543602329395690543893002632342847390262528563101453631249",
+ "priv": "3869546352939126828",
+ "pub": {
+ "x": "6720998227678997862056065758423468898696765396061103319165320094892123609873436621956927659616430754429175531680314970144575484170937282114734236995059907",
+ "y": "2003255176718186448340845419020045861110144816399942495121761020685163741410813659523959485182952080618589282628742821716456883221758277320065970072749767"
+ }
+ },
+ "6F": {
+ "a": "1",
+ "b": "0",
+ "g": {
+ "x": "6464843717418133735350547053515475778344693639024297083670152453169368890450323923057570219956033906732739260071296584266078403106097888400759227671538840",
+ "y": "9802365608931776066980581236074358226130081342122326693663228810170194081027404376238454288409068520245842376896956013827181454200170072948973188347655629"
+ },
+ "n": "5064326794500099449",
+ "p": "13069794699791756704189283477531321752185768325109229180654706539216914049959643607566051851562718277740945064072928161942644694593905061043501953558640041",
+ "priv": "2856600130016981227",
+ "pub": {
+ "x": "3608891578799420548064242341130979159300986828365903896199916298549555232779496232070487208987261916927986279752225486510247880917695587207797815410800112",
+ "y": "2722176554008414613022470486740120254761973593863438540172205830504544349495719796772982904061412103055237821871522377038358032426309577871539448197288775"
+ }
+ },
+ "70": {
+ "a": "1",
+ "b": "0",
+ "g": {
+ "x": "5389546399497383505643339185027973574488379777748198998812201639710214387213898471104888496236804736102752583569918015964707826425506327644196688351201929",
+ "y": "7956467826288064895206371560357238846741050185295208711880364013302186161614207664511000208569082078103634173071766883312441579579905542193148845869579143"
+ },
+ "n": "5339903025552992597",
+ "p": "11383820622080743851306029214182718080855563154181355541498743853491046043538336594620813164814051012924415120005823675884185274830944198875192726828265297",
+ "priv": "396641423549071325",
+ "pub": {
+ "x": "4695611003072950439490860811715007879669129845556910215314788110597779740229935282258327560673417982491463260121432416602363485729459649143131110127087045",
+ "y": "6335169977515592223387188318936371046908706559452644346462225122927979415760150745168231518170807631192680472992856055225104388051689747313878588197029948"
+ }
+ },
+ "71": {
+ "a": "1",
+ "b": "0",
+ "g": {
+ "x": "1636919066913746052919832040843210318286730178861423234687788099864972104581671124532507524370547980246596016229405683487682026261642777380617823294738580",
+ "y": "8466487901883777715027363848813212395026109558207810686428710627247536647256020781313531181797195083740547935858952610950914373644884995559569903061264334"
+ },
+ "n": "5306514456935955013",
+ "p": "10647285162554269224437695647724644839843119123293152705260470723048638640392450736229016524149520637767470359801248882235773639225623705965188263473055241",
+ "priv": "5088986700518482765",
+ "pub": {
+ "x": "4444462983853636224300903512995958460050188507254806791191791256055298236823091859729120712412864370200152404614754508787290867455001456826342902700637917",
+ "y": "8115568718161189589702153176147580377339781121652509698822568933276726613008898585419859020450085118727653691169373824943918335361045551596156823965167303"
+ }
+ },
+ "72": {
+ "a": "1",
+ "b": "0",
+ "g": {
+ "x": "514688672916436233994161866794460347921004624445336466549889111949979570458430209143298647816567735934205299740808658859954412673965256662874089964210056",
+ "y": "9995294546745646065496072326685156090339741118925319171191813074822132326973469946137404060320500451170644477034799477341018109266479655922066570452247716"
+ },
+ "n": "4681756002846077489",
+ "p": "11576556656529186012421026869176068822191939852961823815901517714210326929093532615739621005695997271266436050043753102374986996342830833622067589326388969",
+ "priv": "4510257164279549783",
+ "pub": {
+ "x": "3478231313569920458772498793879691471856552727322308910628099351215228445389873416888062579522801351494016192730153657655217477112588905554343210299716517",
+ "y": "6500875161578073640589890408192252366627924611095176220733269377679556071604406317317453082550115855496867392114150628212712970033976710932220030432101519"
+ }
+ },
+ "73": {
+ "a": "1",
+ "b": "0",
+ "g": {
+ "x": "7493988628096968862823664823307296783957265442603866618618110868279206014282889488854546016472649128814479181728346833784499947792274520912736638959612599",
+ "y": "1237214294261592141546045842651756310953944913968748462046491328891515990492280751925199446437305837893595738492220539506515635435706714684897596147387195"
+ },
+ "n": "5086946079577016329",
+ "p": "9343318003498310132807380534256947890601710761353122442766185787711033046735551269634576058634285039774281723160183108444844064019859933049793739915179009",
+ "priv": "914281843730176555",
+ "pub": {
+ "x": "3382203590685547085271879633172121833516414567880372264838009362757659475490298146019913769048698446555922621211732738922717856485380323106216905509276817",
+ "y": "1000610561129594778538440123955424526230678540958926156884965335647173683312264329023675614706609625010744931986109897483719101576592262078903431731273705"
+ }
+ },
+ "74": {
+ "a": "1",
+ "b": "0",
+ "g": {
+ "x": "520282615406607935808830413235837609227529008118239433194891765554084261177667142590192616462797266047427714603514505726507565809100858610756034340614180",
+ "y": "4557046395510954851157569206449480560848332315791566919607580280750304632075435589109908909351625686398512699199297926705742962219032991805095344264722444"
+ },
+ "n": "4633201844252750473",
+ "p": "7181106593102322766813520532476531209871483588988471009176871145241389568314039093657656718839885029493125387894856821599452867350054864568294961595970889",
+ "priv": "4329540238250287790",
+ "pub": {
+ "x": "1748427561645745685508888890965804844329037567281415535239953290167653001827496844268667372126127464466687812723744919132659150838866693283679107969476861",
+ "y": "6808711632346399211426562555523956018872055718394662707289722207520029794097689415773036615424757895159410496488301598927496012713658489637493990459415502"
+ }
+ },
+ "75": {
+ "a": "1",
+ "b": "0",
+ "g": {
+ "x": "3970421503592305806162067723385709415592786314716896691566248833585082875504539058115488199826473702792925925118152558094421770503793167297677060024718927",
+ "y": "5554883105100816924956214909142063182467429753687518086358166201697075386873889702658647183787469227480685699761636254567290136343644815706400210445911313"
+ },
+ "n": "4969620768775003333",
+ "p": "9367329192536614353969825571614784746581688133872824941332015624935819730507282545479782208538086552891932718692035451653750509854673642536729217033200809",
+ "priv": "1900542198084112697",
+ "pub": {
+ "x": "4353876892698321681359683809542869088530852337838122569824839215556706068138042362107206144376439479309074833553075054210218907784959548685449627846808344",
+ "y": "8262695428675693411183184536456322786716473350154493786858023121139149995844800363332075756178523197170309252869968129569021002560420175757226928859306184"
+ }
+ },
+ "76": {
+ "a": "1",
+ "b": "0",
+ "g": {
+ "x": "6326551563910718268860528254182327162091771902430601493531451083387374814208793911917707468796597151101927661333905356946188279766917640124582958309860223",
+ "y": "1070939833770515876953738253775279333650953871522614246378730556569847770415087819663060576674895214837309111371821715690161251734047871162684076823994031"
+ },
+ "n": "5163299747175235373",
+ "p": "12708432680338950663024943793859785104581558550873132176922502140944191572407504723280648344247213496510204818459572682343834733112791489996438713040722713",
+ "priv": "2660955595284853684",
+ "pub": {
+ "x": "6242149072335025632559475868177651014561453894178094117010887245677593679241492483284846487839452047063166275673350473977054088557780944863637669565510554",
+ "y": "3760738618343905447289077838842452118273372656125827633914088045601193318654337590272033382460648605110939282289108926234152882071866300411987249966508392"
+ }
+ },
+ "77": {
+ "a": "1",
+ "b": "0",
+ "g": {
+ "x": "3441050911814020300444749192946516202643066958085679688027527635336078902570565357794034613670626857779733628280400414152126780414764787508880467081860230",
+ "y": "5189320347313561973406198020606711527037020787040344747711023973754680065919420169373815221081012403792484634209797912175185428156757190356384386028903758"
+ },
+ "n": "5636379957395702917",
+ "p": "6808067327080679111966513889587167521833452796360394631731514300074163927499269804607689186677289253368624547532395593132495277053846962051715214181067049",
+ "priv": "4770366445246647919",
+ "pub": {
+ "x": "3784836821009804623908562657454067031620663920795503120922284803393053289924770294999614270091654880731937397954708819499104008236108939544584465970575657",
+ "y": "2548919863312637994982110323128716593443554585384998865096038925317491021809963517729332500037065987812015306586164359013687108554846531794456419424978166"
+ }
+ },
+ "78": {
+ "a": "1",
+ "b": "0",
+ "g": {
+ "x": "6088849103151287598200503614952681450041235940107949935585195235760674294068839175308064812005993699240723781065167790033914861747640550740417495607524878",
+ "y": "6437044994712923133562556419973977745775332692424042838255481451539737092550676452397324770744709191355968135868892506010949492147308988716192132134358758"
+ },
+ "n": "5665947320131757957",
+ "p": "11487665893367899222355107344421070168598636715559742001518755192280067788122295545642125078713810151473262732817187528724738814802926117239350729502549313",
+ "priv": "1638384434777494607",
+ "pub": {
+ "x": "6817164663422195178935018212244470984673598663732878715315353947093076546158158779927934784011339749197794005942254786198555667040118869215996525225725756",
+ "y": "479405963135164984275171241854667955936410731405160278776735030096152430051382537471685764957967298232387289150592192840276297820432357414249749375873921"
+ }
+ },
+ "79": {
+ "a": "1",
+ "b": "0",
+ "g": {
+ "x": "4168032131084289399335071645344208509979609398979750639892803067976802982383377642994794290997664281252255327088446719315748049734788709518142590431805660",
+ "y": "1656209550366422132691297571615381854289591319278684544108854043570071112749978525132034103704697219285285628389328976303066367524722775405286718455955564"
+ },
+ "n": "4960271072399676893",
+ "p": "10021555678719333461534229671415111186370042343731278260845563503712408730714909065839911647708728633864627592037548672867112257016466864674007767253922097",
+ "priv": "2358235241063744504",
+ "pub": {
+ "x": "6268444080236314304093021923163692883947231122425324957435993511331396945928289709553768144715272511191776892202607956944672817602546659847392056974920413",
+ "y": "4521790106135273903362564196182573571911305322710028936326839181289858330729925650095457264860694569235728467176857352508520633869306739331785585988490424"
+ }
+ },
+ "7C": {
+ "a": "1",
+ "b": "0",
+ "g": {
+ "x": "12595907217201908356295407841191662128058183862583575051215311157290088461747744112833552590366680246352682673545573818921176626985849350979877835633501977",
+ "y": "4081991768131203059718114067775041458907360041704484571923047903596118063845158964417046054534517243002541376413074492688094692161600554230539596132297166"
+ },
+ "n": "4713366068048639461",
+ "p": "12740026520322163229338101893927031288254298898961140709601703660346758023771809107598270422219922815511074525617226446729563727652140299854867827057762097",
+ "priv": "3645140886299655136",
+ "pub": {
+ "x": "4170165600612835816072752153717064792837383941694916018487245065025874460597138155904045581814180291752254925515125393268789405330284361917814339072483163",
+ "y": "4283440682806037636477705431155033208671204005459162418818595162913967275642251903764442509383091895637321243673549727387249130320635242869060716707502660"
+ }
+ },
+ "7D": {
+ "a": "1",
+ "b": "0",
+ "g": {
+ "x": "1590489240729454536846927296249670028298807614755534958905007219831873392287176796614856253574534913794562411622281212983602673653939841066950081049752496",
+ "y": "11517876747503444279939611612149114290500110474847041028675128176427946481265362028336760831240812613962174827348163472218433846119323659870013646187498844"
+ },
+ "n": "5294246881599156289",
+ "p": "11605813619242976573270030739417432742386383152135543814151806150509223544935055861898978057855680549288259905678657401053040643579124366975449696646547113",
+ "priv": "3382444905344124117",
+ "pub": {
+ "x": "7139013373449136481922723685952126978522016553107297658292982499195579631402843387844844515956102856833439560057624352734539807208111600469232003834742726",
+ "y": "11564220690727719123783272341292762734247468339612099884983311964463919067661268492589581551223830761015103439215183156282987937329176448399493410863081658"
+ }
+ },
+ "7E": {
+ "a": "1",
+ "b": "0",
+ "g": {
+ "x": "1575309437054948209501943095287709278853331993476275043905717126838899378449873652295206985577659276472511880241134171582107274631299115230531386131157999",
+ "y": "6650274808069442841806032562188313712099529938370090595758338521093982842067346153375754672029991541735693798661861664375806224952650375004336458985666606"
+ },
+ "n": "4969253191813446413",
+ "p": "9069158124012783386919261859891326104095932201604665726925475589116835230298742553224266302713449742557574534803913789744550176999999570003705214704390217",
+ "priv": "633440952939337400",
+ "pub": {
+ "x": "6737291019107330377138239698781147037798498698085590227826737297136831202209658011712450579352335182691931564512305715765043903899386154655983121712134496",
+ "y": "6478740397369612151863528145504753617290168688973289065350048115368485718043346919007738307138223600887324712066864911651041752553131216074853313955876490"
+ }
+ },
+ "7F": {
+ "a": "1",
+ "b": "0",
+ "g": {
+ "x": "10741485864258239198808785058735575359552883054178990682157071986056378748243908275065774911693686879557176115248830467599801081049714644498962624953002215",
+ "y": "11478849728134996491513678201481114137233934272403186543739198184491575177652244835264134301889794968575917067111000421718189993813699108582748277627331424"
+ },
+ "n": "4717216669495499909",
+ "p": "11629054801211706004419443560137925342280675682563984850356336001042892658038876793698258083522548784740766252109524130264962268004130304432618675290754433",
+ "priv": "1978738820593283754",
+ "pub": {
+ "x": "10365357351159597511691869898607967487759410765693427025769355019639442762848113011873038330791205382321415453886281547469084230058652569483640290427689765",
+ "y": "3630424016244283654991032347706596357280799286722217672143586671366363275733536816197706717283628695319640288198134598259206639481908864297539186688658667"
+ }
+ },
+ "80": {
+ "a": "1",
+ "b": "0",
+ "g": {
+ "x": "8580403238882100235051542355383721701957907551038579039606823679429370998618477107998272205809779979070424836909055332203760134183582196032565738191416290",
+ "y": "8089518457353381291703015153167928502980155426796939360253964740120600669024761032460910890439561234792725982282867894017503793419414413700802430009921348"
+ },
+ "n": "5749430925149106037",
+ "p": "10346760583571096176856644232540829964140154551711351621271787144406751946103364695457404414101548368379536264694684184927538790127181041198956087282638713",
+ "priv": "1645776849061114653",
+ "pub": {
+ "x": "2693318663394724629536224434719920577877813174957928953548110650108753626458451559742749689181138903486875892329303418974795190532736471941235039052866017",
+ "y": "9731351279101954720322874114402530628478997829499955147172294887000756356675120252590103495090489444217180061611275014585059693660157883498077947452829308"
+ }
+ },
+ "81": {
+ "a": "1",
+ "b": "0",
+ "g": {
+ "x": "7437963515044744382041063003990186061951963674556830147184970263069293479283937679956030294774873724521466287595837030336839893434007328816593628527951139",
+ "y": "8119523013457518610939772676897260374300215324174888451710880106546482206568332630653184281728054177911608701029171061542711266521921027618944809700269020"
+ },
+ "n": "4664659198522599761",
+ "p": "8803652642367490686800500812152951141533039658262067265584900306384497036408043913960439010879485280456295963028944969684231373465236681815575854801801537",
+ "priv": "679507843451681370",
+ "pub": {
+ "x": "5985625186844163955999843168360558757526930565271797482532035434301622557557888304828323051687996364196567917002859433230045770986014082720007536379232286",
+ "y": "5095137563952044397893925476372801628807819070844068253860097589794304444869339214045112157290439689311317894679583840560004967976871983537219500930078926"
+ }
+ },
+ "82": {
+ "a": "1",
+ "b": "0",
+ "g": {
+ "x": "5227772111321015780185186378724461401389838650015203302651549706092755180467439665164380531103769615828715419899860401082742849422956824981581313597347874",
+ "y": "1151126907155345114356142690744246053451710101245891176496132941203621694723865469418399701772737205845553807980389383148927963646671033999895601474687519"
+ },
+ "n": "5054413088652069853",
+ "p": "7296578671400180846340488819765224221032599696154274327503058673792604932489024645402035468500749839406774778822529582585837048996841112334675208148008273",
+ "priv": "1518752543107066987",
+ "pub": {
+ "x": "4943135394525378761513066941942646996630904108674369673596779077435853058745531048405707407834162897708884740422690900167561316611219129119275902078074219",
+ "y": "6735462303321596804740537199356216806938426989646803957550767635543166255178877986982448754493882586721252959635808383783210872383900712878226874328425289"
+ }
+ },
+ "83": {
+ "a": "1",
+ "b": "0",
+ "g": {
+ "x": "5695095101976550933576792098222206444121927711857099953946493227368612976937692219148904832759052785374432508483206550560670798020904713813215695847589801",
+ "y": "4784422034620378423461700755190489419946091495999011373191971887281563234726587597967924056781298693580929934196186459792215137044322902158637883848206160"
+ },
+ "n": "5606861943932384357",
+ "p": "11870235722842965793915717289164026915525574991697293904376629205435775162253052338892386378423782853838596832972630793988864239781894306253881693229739449",
+ "priv": "2827273490206920704",
+ "pub": {
+ "x": "5798013553367225625398424944951648719498151375103154272402146280858925589444004802702185901348087197531033136089765892317962373259242520894688005737863471",
+ "y": "9951766927130077074693523962049666695328886664964251829029028233627647859185002333988456603917629184050956057303841353135661823086259678507339936694140074"
+ }
+ },
+ "84": {
+ "a": "1",
+ "b": "0",
+ "g": {
+ "x": "5560427793695630869020488047042192811305372437924695179205785948174621879035697162554246234811767536148226584483155664003903180522305522332791117231929666",
+ "y": "8363507240870059025148603462375399778510363881280730362369926390337468582944357036539945658952697391101011344937374311682301614715537178578854285685197751"
+ },
+ "n": "5278662156374609929",
+ "p": "8510236036207253068508614967428092266661773054007334596390902004993409037244437599270481895235147192065946981872962110815581510080900322230030613433609929",
+ "priv": "1460840063674431942",
+ "pub": {
+ "x": "1596613556377662160548714309781670944367097433768876984270422914199277552144598881727442116643470093788384843191285815571989032391323299101906136701074247",
+ "y": "6779226255898830514962686943250906557829410143670351051280134459463818406443572593281528353692074367536339902467178858221068918742809756956394043773888481"
+ }
+ },
+ "85": {
+ "a": "1",
+ "b": "0",
+ "g": {
+ "x": "7505394603001954455294446586132986541793661313187851848400138712640114877635087676739162227532381665370139572899712018167266674761334262252602951266506818",
+ "y": "1680934674915492204617657824564571651266351348781478568848386763197847836921805135275742806664744209970767209281144265127261059782147782754056266540269863"
+ },
+ "n": "5570981815749140209",
+ "p": "8732795211981967719223853752484420568831774283007885254650070724992722784292199925344685033347762258503637529768918721006025869309189556401554954935365617",
+ "priv": "3812804900780147318",
+ "pub": {
+ "x": "4198091971144571806535249777589229216025698044556471495675027203140959357482044604829990385570926652328279194279219793976552272247701255490650281936560485",
+ "y": "7376523713920169817088204303475736190857293501666832093768268558780265806170011129510363866615123592937684499422116009654937439554855961356059515891735709"
+ }
+ },
+ "86": {
+ "a": "1",
+ "b": "0",
+ "g": {
+ "x": "6703694613653843120011692431117258849910799069682325777498755184030060953999731560412255683835043874631157157087206805847404428652396182573664804587133112",
+ "y": "5277626791685622402975349130840409135234562392945730176174183499747960262261554444679677984020548127978314810292949910774355538747468714862507226400578050"
+ },
+ "n": "4965203940861890461",
+ "p": "6920390285079512273302696404582911972264578475868268336762086064690280720220547446570404290836148341928470331899722422605152853844455708186803401682318609",
+ "priv": "3630631387672505590",
+ "pub": {
+ "x": "3478488282863377607849104510962918772905907619241086883516775385578422433058222721622377015359616954614527499756095170836870833349744894938045767729374604",
+ "y": "6516229707236511212709386515668071803217486988049002197368773083245438043750468395538828485641993141409937876246800956189497344080209589752539139161857067"
+ }
+ },
+ "87": {
+ "a": "1",
+ "b": "0",
+ "g": {
+ "x": "8492237021199611805216211235692828503490134263808640227201471417783835722620711359672191414279197757339092746832374771649463193205606483563070732207239103",
+ "y": "9066857546008909834699517292838576515096976755324771652036838427393784614802721995536572813787704837591635506894617712897267720603865495180642056286777930"
+ },
+ "n": "5395913001602193001",
+ "p": "12003791098642037621560892862199749337206731482824811053973184067477553933302251555963517648909225129426028229957803674277229810351232349352687771411098657",
+ "priv": "3700906348658367772",
+ "pub": {
+ "x": "5775825242226756571502583787399598340972935199546526848543059173637629885244704205615625248092598199469055373643573971908421374152957312277973710643538365",
+ "y": "10911683546275695747340854250863118879557596394002273165043521944703658224362918974724490418230578464274815505046139470607624648137251847635946257817835207"
+ }
+ },
+ "88": {
+ "a": "1",
+ "b": "0",
+ "g": {
+ "x": "4613903814166119429696577406821167971645163774499019682043327030213494538193533493049691578856679354333108466765986838529606605477163191099856754482133624",
+ "y": "3521468031000279806241876387398981937866053227587991515566136905082530906473751110192089214709190433958327882109862961460387650131889271308175622463720393"
+ },
+ "n": "5128048066639829053",
+ "p": "9639141353904923039979046809026012240224510644742503259454894126544223802678735442941322199545077147700061934760834787308248101230365644459023150446592073",
+ "priv": "4304573455044199124",
+ "pub": {
+ "x": "9115943070793793803217108546177493293013456009143806171877810710292493847846923418474866643754633777121093635194496777485003447640027563970977306732858130",
+ "y": "299091567560127519026074100988936504880710957160222942376926725629153626609589321204043645296136878702192317324679172359631365142213939438050305091264565"
+ }
+ },
+ "89": {
+ "a": "1",
+ "b": "0",
+ "g": {
+ "x": "6294301350876969072049859821523351247996356876707594294091972829683736926378761574970824207105787060479701683177802567747400920435316295166884106436372464",
+ "y": "7865276036147040765315639393821914531861795557520800252404014078372729976880891252631787770100036988799613474283906061454839256755579930624307713972233136"
+ },
+ "n": "5260598915664139109",
+ "p": "9788455676437959684897980727280589939325587387415117741017124676835427061115080584919771672642444455807393540858421196568448000473956486045538255860564609",
+ "priv": "3166676722827298860",
+ "pub": {
+ "x": "7054010135762396846749770891818718069638437011522328604158065395187521207404324203344826428948442924552015830577386735751163813940938294977917580839175333",
+ "y": "6907491873002602436260770112009167552099295226221829271071772648575964850189443824766022140586160426909373840561095003562834548795561414117018465995425960"
+ }
+ },
+ "FE": {
+ "a": "1",
+ "b": "0",
+ "g": {
+ "x": "10692194187797070010417373067833672857716423048889432566885309624149667762706899929433420143814127803064297378514651",
+ "y": "14587399915883137990539191966406864676102477026583239850923355829082059124877792299572208431243410905713755917185109"
+ },
+ "n": "629063109922370885449",
+ "p": "21782971228112002125810473336838725345308036616026120243639513697227789232461459408261967852943809534324870610618161",
+ "priv": "153862071918555979944",
+ "pub": {
+ "x": "3917395608307488535457389605368226854270150445881753750395461980792533894109091921400661704941484971683063487980768",
+ "y": "8858262671783403684463979458475735219807686373661776500155868309933327116988404547349319879900761946444470688332645"
+ }
+ },
+ "FF": {
+ "a": "1",
+ "b": "0",
+ "g": {
+ "x": "18999816458520350299014628291870504329073391058325678653840191278128672378485029664052827205905352913351648904170809",
+ "y": "7233699725243644729688547165924232430035643592445942846958231777803539836627943189850381859836033366776176689124317"
+ },
+ "n": "675048016158598417213",
+ "p": "28688293616765795404141427476803815352899912533728694325464374376776313457785622361119232589082131818578591461837297",
+ "priv": "100266970209474387075",
+ "pub": {
+ "x": "7147768390112741602848314103078506234267895391544114241891627778383312460777957307647946308927283757886117119137500",
+ "y": "20525272195909974311677173484301099561025532568381820845650748498800315498040161314197178524020516408371544778243934"
+ }
+ }
+ },
+ "Activation": {
+ "Windowws XP": {
+ "p": "102011604035381881",
+ "x": {
+ "0": "0",
+ "1": "9433814980383617",
+ "2": "19168316694801104",
+ "3": "90078616228674308",
+ "4": "90078616228674308",
+ "5": "1"
+ },
+ "mul": "65537",
+ "priv": "1315384396487572637498562978064321",
+ "iid_key": "1791516372"
+ },
+ "Windows XP Plus! Digital Media Edition": {
+ "p": "101996933280717187",
+ "x": {
+ "0": "14442243999705614",
+ "1": "88154401999011195",
+ "2": "86996763276881336",
+ "3": "95455813375647760",
+ "4": "6252462837094107",
+ "5": "1"
+ },
+ "mul": "65537",
+ "priv": "2752030625102368166730185283969067",
+ "iid_key": "1791516372"
+ },
+ "Office XP / Office 2003": {
+ "p": "103099955908255721",
+ "x": {
+ "0": "0",
+ "1": "64728167274549202",
+ "2": "4488766805843809",
+ "3": "70698430483539942",
+ "4": "64728167274549202",
+ "5": "1"
+ },
+ "mul": "65537",
+ "priv": "10294349293510589382098112327865153",
+ "iid_key": "1513142771"
+ }
+ }
+}
\ No newline at end of file
diff --git a/umskt/Cargo.toml b/umskt/Cargo.toml
index 0957c9a..701f790 100644
--- a/umskt/Cargo.toml
+++ b/umskt/Cargo.toml
@@ -6,12 +6,7 @@ edition = "2021"
[dependencies]
anyhow = "1.0.71"
bitreader = "0.3.7"
-elliptic-curve = "0.13.5"
-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"
+openssl = { git = "https://github.com/sfackler/rust-openssl" }
thiserror = "1.0.40"
[dev-dependencies]
diff --git a/umskt/src/bink1998.rs b/umskt/src/bink1998.rs
index 67cd059..cd8556a 100644
--- a/umskt/src/bink1998.rs
+++ b/umskt/src/bink1998.rs
@@ -1,24 +1,20 @@
-//! Structs to deal with older BINK (< `0x40`) product keys
-use std::{
- cmp::Ordering,
- fmt::{Display, Formatter},
-};
+use std::fmt::{Display, Formatter};
use anyhow::{bail, Result};
use bitreader::BitReader;
-use num_bigint::{BigInt, BigUint, RandomBits};
-use num_integer::Integer;
-use num_traits::{FromPrimitive, ToPrimitive};
-use rand::Rng;
-use sha1::{Digest, Sha1};
+use openssl::{
+ bn::{BigNum, BigNumContext, MsbOption},
+ ec::{EcGroup, EcPoint},
+ sha::sha1,
+};
use crate::{
- crypto::{EllipticCurve, Point, PrivateKey},
+ crypto::{EllipticCurve, PrivateKey},
key::{base24_decode, base24_encode, strip_key},
math::bitmask,
};
-const FIELD_BITS: u64 = 384;
+const FIELD_BITS: i32 = 384;
const FIELD_BYTES: usize = 48;
const SHA_MSG_LENGTH: usize = 4 + 2 * FIELD_BYTES;
@@ -27,9 +23,6 @@ const SERIAL_LENGTH_BITS: u8 = 30;
const UPGRADE_LENGTH_BITS: u8 = 1;
const EVERYTHING_ELSE: u8 = HASH_LENGTH_BITS + SERIAL_LENGTH_BITS + UPGRADE_LENGTH_BITS;
-/// A product key for a BINK ID less than `0x40`
-///
-/// Every `ProductKey` contains a valid key for its given parameters.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct ProductKey {
upgrade: bool,
@@ -40,9 +33,6 @@ pub struct ProductKey {
}
impl ProductKey {
- /// Generates a new product key for the given parameters.
- ///
- /// The key is verified to be valid before being returned.
pub fn new(
curve: &EllipticCurve,
private_key: &PrivateKey,
@@ -54,117 +44,101 @@ impl ProductKey {
let sequence = match sequence {
Some(serial) => serial,
None => {
- let mut rng = rand::thread_rng();
- let random: BigInt = rng.sample(RandomBits::new(32));
- let raw = u32::from_be_bytes(random.to_bytes_be().1[0..4].try_into().unwrap());
- raw % 999999
+ let mut bn_rand = BigNum::new()?;
+ bn_rand.rand(19, MsbOption::MAYBE_ZERO, false)?;
+ let o_raw = u32::from_be_bytes(bn_rand.to_vec_padded(4)?.try_into().unwrap());
+ o_raw % 999999
}
};
// Default to upgrade=false
let upgrade = upgrade.unwrap_or(false);
- let private = &private_key.gen_order - &private_key.private_key;
-
// Generate a new random key
let product_key = Self::generate(
- curve,
+ &curve.curve,
&curve.gen_point,
&private_key.gen_order,
- &private,
+ &private_key.private_key,
channel_id,
sequence,
upgrade,
)?;
// Make sure the key is valid
- product_key.verify(curve, &curve.gen_point, &curve.pub_point)?;
+ product_key.verify(&curve.curve, &curve.gen_point, &curve.pub_point)?;
// Ship it
Ok(product_key)
}
- /// Validates an existing product key string and tried to create a new `ProductKey` from it.
- ///
- /// # Arguments
- ///
- /// * `curve` - The elliptic curve to use for verification.
- /// * `key` - Should be 25 characters long, not including the (optional) hyphens.
pub fn from_key(curve: &EllipticCurve, key: &str) -> Result {
let key = strip_key(key)?;
let Ok(packed_key) = base24_decode(&key) else {
bail!("Product key is in an incorrect format!")
};
let product_key = Self::from_packed(&packed_key)?;
- product_key.verify(curve, &curve.gen_point, &curve.pub_point)?;
+ product_key.verify(&curve.curve, &curve.gen_point, &curve.pub_point)?;
Ok(product_key)
}
fn generate(
- e_curve: &EllipticCurve,
- base_point: &Point,
- gen_order: &BigInt,
- private_key: &BigInt,
+ e_curve: &EcGroup,
+ base_point: &EcPoint,
+ gen_order: &BigNum,
+ private_key: &BigNum,
channel_id: u32,
sequence: u32,
upgrade: bool,
) -> Result {
+ 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 data = serial << 1 | upgrade as u32;
- let mut rng = rand::thread_rng();
-
let product_key = loop {
- let c: BigUint = rng.sample(RandomBits::new(FIELD_BITS));
- let c: BigInt = c.into();
+ let mut r = EcPoint::new(e_curve)?;
- let r = e_curve.multiply_point(&c, base_point);
+ // Generate a random number c consisting of 384 bits without any constraints.
+ c.rand(FIELD_BITS, MsbOption::MAYBE_ZERO, false)?;
- let (x, y) = match r {
- Point::Point { x, y } => (x, y),
- Point::Infinity => bail!("Point at infinity!"),
- };
+ // Pick a random derivative of the base point on the elliptic curve.
+ // R = cG;
+ r.mul(e_curve, base_point, &c, &num_context)?;
+
+ // Acquire its coordinates.
+ // x = R.x; y = R.y;
+ 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 x_bin = x.to_bytes_le().1;
- let x_bin = match x_bin.len().cmp(&FIELD_BYTES) {
- Ordering::Less => (0..FIELD_BYTES - x_bin.len())
- .map(|_| 0)
- .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,
- };
+ let mut x_bin = x.to_vec_padded(FIELD_BYTES as i32)?;
+ x_bin.reverse();
+ let mut y_bin = y.to_vec_padded(FIELD_BYTES as i32)?;
+ y_bin.reverse();
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 + FIELD_BYTES..4 + FIELD_BYTES * 2].copy_from_slice(&y_bin);
- let msg_digest = {
- let mut hasher = Sha1::new();
- hasher.update(msg_buffer);
- hasher.finalize()
- };
+ let msg_digest = sha1(&msg_buffer);
let hash: u32 =
u32::from_le_bytes(msg_digest[0..4].try_into().unwrap()) >> 4 & bitmask(28) as u32;
- let mut ek = private_key.clone();
- ek *= hash;
+ ek = (*private_key).to_owned()?;
+ 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) {
break Self {
@@ -182,43 +156,36 @@ impl ProductKey {
fn verify(
&self,
- e_curve: &EllipticCurve,
- base_point: &Point,
- public_key: &Point,
+ e_curve: &EcGroup,
+ base_point: &EcPoint,
+ public_key: &EcPoint,
) -> Result {
- let e = BigInt::from_u32(self.hash).unwrap();
- let s = BigInt::from_u64(self.signature).unwrap();
+ let mut ctx = BigNumContext::new()?;
- let t = e_curve.multiply_point(&s, base_point);
- let mut p = e_curve.multiply_point(&e, public_key);
+ let e = BigNum::from_u32(self.hash)?;
+ 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 {
- Point::Point { x, y } => (x, y),
- Point::Infinity => bail!("Point at infinity!"),
- };
+ t.mul(e_curve, base_point, &s, &ctx)?;
+ p.mul(e_curve, public_key, &e, &ctx)?;
+
+ {
+ 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 x_bin = x.to_bytes_le().1;
- let x_bin = if x_bin.len() < FIELD_BYTES {
- (0..FIELD_BYTES - x_bin.len())
- .map(|_| 0)
- .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 mut x_bin = x.to_vec_padded(FIELD_BYTES as i32)?;
+ x_bin.reverse();
+ let mut y_bin = y.to_vec_padded(FIELD_BYTES as i32)?;
+ y_bin.reverse();
let serial = self.channel_id * 1_000_000 + self.sequence;
let data = serial << 1 | self.upgrade as u32;
@@ -227,11 +194,7 @@ impl ProductKey {
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);
- let msg_digest = {
- let mut hasher = Sha1::new();
- hasher.update(msg_buffer);
- hasher.finalize()
- };
+ let msg_digest = sha1(&msg_buffer);
let hash: u32 =
u32::from_le_bytes(msg_digest[0..4].try_into().unwrap()) >> 4 & bitmask(28) as u32;
@@ -302,7 +265,7 @@ mod tests {
use serde_json::from_reader;
- use crate::{bink1998, crypto::EllipticCurve};
+ use crate::crypto::EllipticCurve;
#[test]
fn verify_test() {
@@ -320,15 +283,16 @@ mod tests {
let p = bink["p"].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 gy = bink["g"]["y"].as_str().unwrap();
let kx = bink["pub"]["x"].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!(bink1998::ProductKey::from_key(&curve, "11111-R6BG2-39J83-RYKHF-W47TT").is_err());
+ assert!(super::ProductKey::from_key(&curve, product_key).is_ok());
+ assert!(super::ProductKey::from_key(&curve, "11111-R6BG2-39J83-RYKHF-W47TT").is_err());
}
#[test]
diff --git a/umskt/src/bink2002.rs b/umskt/src/bink2002.rs
index 924ad25..96e37fb 100644
--- a/umskt/src/bink2002.rs
+++ b/umskt/src/bink2002.rs
@@ -1,24 +1,21 @@
-//! Structs to deal with newer BINK (>= `0x40`) product keys
-use std::{
- cmp::Ordering,
- fmt::{Display, Formatter},
-};
+use std::fmt::{Display, Formatter};
use anyhow::{bail, Result};
use bitreader::BitReader;
-use num_bigint::{BigInt, BigUint, RandomBits};
-use num_integer::Integer;
-use num_traits::ToPrimitive;
-use rand::Rng;
-use sha1::{Digest, Sha1};
+use openssl::{
+ bn::{BigNum, BigNumContext, MsbOption},
+ ec::{EcGroup, EcPoint},
+ rand::rand_bytes,
+ sha::sha1,
+};
use crate::{
- crypto::{mod_sqrt, EllipticCurve, Point, PrivateKey},
+ crypto::{EllipticCurve, PrivateKey},
key::{base24_decode, base24_encode, strip_key},
math::{bitmask, by_dword, next_sn_bits},
};
-const FIELD_BITS: u64 = 512;
+const FIELD_BITS: i32 = 512;
const FIELD_BYTES: usize = 64;
const SHA_MSG_LENGTH: usize = 3 + 2 * FIELD_BYTES;
@@ -29,9 +26,6 @@ const UPGRADE_LENGTH_BITS: u8 = 1;
const EVERYTHING_ELSE: u8 =
SIGNATURE_LENGTH_BITS + HASH_LENGTH_BITS + CHANNEL_ID_LENGTH_BITS + UPGRADE_LENGTH_BITS;
-/// A product key for a BINK ID `0x40` or higher
-///
-/// Every `ProductKey` contains a valid key for its given parameters.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct ProductKey {
upgrade: bool,
@@ -42,9 +36,6 @@ pub struct ProductKey {
}
impl ProductKey {
- /// Generates a new product key for the given parameters.
- ///
- /// The key is verified to be valid before being returned.
pub fn new(
curve: &EllipticCurve,
private_key: &PrivateKey,
@@ -56,10 +47,9 @@ impl ProductKey {
let auth_info = match auth_info {
Some(auth_info) => auth_info,
None => {
- let mut rng = rand::thread_rng();
- let random: BigInt = rng.sample(RandomBits::new(32));
- let raw = u32::from_be_bytes(random.to_bytes_be().1[0..4].try_into().unwrap());
- raw % (bitmask(10) as u32)
+ let mut auth_info_bytes = [0_u8; 4];
+ rand_bytes(&mut auth_info_bytes)?;
+ u32::from_ne_bytes(auth_info_bytes) & ((1 << 10) - 1)
}
};
@@ -68,7 +58,7 @@ impl ProductKey {
// Generate a new random key
let product_key = Self::generate(
- curve,
+ &curve.curve,
&curve.gen_point,
&private_key.gen_order,
&private_key.private_key,
@@ -78,25 +68,19 @@ impl ProductKey {
)?;
// Make sure the key is valid
- product_key.verify(curve, &curve.gen_point, &curve.pub_point)?;
+ product_key.verify(&curve.curve, &curve.gen_point, &curve.pub_point)?;
// Ship it
Ok(product_key)
}
- /// Validates an existing product key string and tried to create a new `ProductKey` from it.
- ///
- /// # Arguments
- ///
- /// * `curve` - The elliptic curve to use for verification.
- /// * `key` - Should be 25 characters long, not including the (optional) hyphens.
pub fn from_key(curve: &EllipticCurve, key: &str) -> Result {
let key = strip_key(key)?;
let Ok(packed_key) = base24_decode(&key) else {
bail!("Product key is in an incorrect format!")
};
let product_key = Self::from_packed(&packed_key)?;
- let verified = product_key.verify(curve, &curve.gen_point, &curve.pub_point)?;
+ let verified = product_key.verify(&curve.curve, &curve.gen_point, &curve.pub_point)?;
if !verified {
bail!("Product key is invalid! Wrong BINK ID?");
}
@@ -104,50 +88,38 @@ impl ProductKey {
}
fn generate(
- e_curve: &EllipticCurve,
- base_point: &Point,
- gen_order: &BigInt,
- private_key: &BigInt,
+ e_curve: &EcGroup,
+ base_point: &EcPoint,
+ gen_order: &BigNum,
+ private_key: &BigNum,
channel_id: u32,
auth_info: u32,
upgrade: bool,
) -> Result {
- 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 key = loop {
- let c: BigUint = rng.sample(RandomBits::new(FIELD_BITS));
- let mut c: BigInt = c.into();
+ let mut r = EcPoint::new(e_curve)?;
- let r = e_curve.multiply_point(&c, base_point);
+ c.rand(FIELD_BITS, MsbOption::MAYBE_ZERO, false)?;
- let (x, y) = match r {
- Point::Point { x, y } => (x, y),
- Point::Infinity => bail!("Point at infinity!"),
- };
+ r.mul(e_curve, base_point, &c, &num_context)?;
+
+ 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 x_bin = x.to_bytes_le().1;
- let x_bin = match x_bin.len().cmp(&FIELD_BYTES) {
- Ordering::Less => (0..FIELD_BYTES - x_bin.len())
- .map(|_| 0)
- .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,
- };
+ let mut x_bin = x.to_vec_padded(FIELD_BYTES as i32)?;
+ x_bin.reverse();
+ let mut y_bin = y.to_vec_padded(FIELD_BYTES as i32)?;
+ y_bin.reverse();
msg_buffer[0x00] = 0x79;
msg_buffer[0x01] = (data & 0x00FF) as u8;
@@ -156,11 +128,7 @@ impl ProductKey {
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);
- let msg_digest = {
- let mut hasher = Sha1::new();
- hasher.update(msg_buffer);
- hasher.finalize()
- };
+ let msg_digest = sha1(&msg_buffer);
let hash: u32 = by_dword(&msg_digest[0..4]) & bitmask(31) as u32;
@@ -176,43 +144,42 @@ impl ProductKey {
msg_buffer[0x09] = 0x00;
msg_buffer[0x0A] = 0x00;
- let msg_digest = {
- let mut hasher = Sha1::new();
- hasher.update(&msg_buffer[..=0x0A]);
- hasher.finalize()
- };
+ let msg_digest = sha1(&msg_buffer[..=0x0A]);
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;
- 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;
- match mod_sqrt(&s, gen_order) {
- Some(res) => s = res,
- None => {
- no_square = true;
- }
- }
+ let s_2 = s.to_owned()?;
+ if s.mod_sqrt(&s_2, gen_order, &mut num_context).is_err() {
+ 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 >>= 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 {
upgrade,
@@ -234,10 +201,12 @@ impl ProductKey {
fn verify(
&self,
- e_curve: &EllipticCurve,
- base_point: &Point,
- public_key: &Point,
+ e_curve: &EcGroup,
+ base_point: &EcPoint,
+ public_key: &EcPoint,
) -> Result {
+ let mut num_context = BigNumContext::new()?;
+
let data = self.channel_id << 1 | self.upgrade as u32;
let mut msg_buffer: [u8; SHA_MSG_LENGTH] = [0; SHA_MSG_LENGTH];
@@ -254,47 +223,39 @@ impl ProductKey {
msg_buffer[0x09] = 0x00;
msg_buffer[0x0A] = 0x00;
- let msg_digest = {
- let mut hasher = Sha1::new();
- hasher.update(&msg_buffer[..=0x0A]);
- hasher.finalize()
- };
+ let msg_digest = sha1(&msg_buffer[..=0x0A]);
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;
- let e = BigInt::from(i_signature);
- let s = BigInt::from(self.signature);
+ let e = BigNum::from_slice(&i_signature.to_be_bytes())?;
+ let s = BigNum::from_slice(&self.signature.to_be_bytes())?;
- let t = e_curve.multiply_point(&s, base_point);
- let mut p = e_curve.multiply_point(&e, public_key);
+ let mut x = BigNum::new()?;
+ let mut y = BigNum::new()?;
- p = e_curve.add_points(&t, &p);
- p = e_curve.multiply_point(&s, &p);
+ let mut p = EcPoint::new(e_curve)?;
+ let mut t = EcPoint::new(e_curve)?;
- let (x, y) = match p {
- Point::Point { x, y } => (x, y),
- Point::Infinity => bail!("Point at infinity!"),
- };
+ t.mul(e_curve, base_point, &s, &num_context)?;
+ p.mul(e_curve, public_key, &e, &num_context)?;
- let x_bin = x.to_bytes_le().1;
- let x_bin = if x_bin.len() < FIELD_BYTES {
- (0..FIELD_BYTES - x_bin.len())
- .map(|_| 0)
- .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 p_2 = p.to_owned(e_curve)?;
+ p.add(e_curve, &t, &p_2, &mut num_context)?;
+ }
+
+ {
+ let p_2 = p.to_owned(e_curve)?;
+ p.mul(e_curve, &p_2, &s, &num_context)?;
+ }
+
+ p.affine_coordinates(e_curve, &mut x, &mut y, &mut num_context)?;
+
+ let mut x_bin = x.to_vec_padded(FIELD_BYTES as i32)?;
+ x_bin.reverse();
+ let mut y_bin = y.to_vec_padded(FIELD_BYTES as i32)?;
+ y_bin.reverse();
msg_buffer[0x00] = 0x79;
msg_buffer[0x01] = (data & 0x00FF) as u8;
@@ -303,11 +264,7 @@ impl ProductKey {
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);
- let msg_digest = {
- let mut hasher = Sha1::new();
- hasher.update(msg_buffer);
- hasher.finalize()
- };
+ let msg_digest = sha1(&msg_buffer);
let hash: u32 = by_dword(&msg_digest[0..4]) & bitmask(31) as u32;
@@ -396,12 +353,13 @@ mod tests {
let p = bink["p"].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 gy = bink["g"]["y"].as_str().unwrap();
let kx = bink["pub"]["x"].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, "11111-YRGC8-4KYTG-C3FCC-JCFDY").is_err());
diff --git a/umskt/src/confid/black_box.rs b/umskt/src/confid/black_box.rs
index 17351c0..688552d 100644
--- a/umskt/src/confid/black_box.rs
+++ b/umskt/src/confid/black_box.rs
@@ -1,26 +1,49 @@
-use std::mem::{size_of, swap};
+use std::{ffi::c_void, ptr};
#[derive(Copy, Clone)]
+#[repr(C)]
struct TDivisor {
u: [u64; 2],
v: [u64; 2],
}
-
#[derive(Copy, Clone)]
-struct Encoded {
+#[repr(C)]
+struct C2RustUnnamed {
+ encoded: [u32; 4],
+}
+#[derive(Copy, Clone)]
+#[repr(C)]
+union C2RustUnnamed0 {
+ c2rust_unnamed: C2RustUnnamed1,
+ c2rust_unnamed_0: C2RustUnnamed,
+}
+#[derive(Copy, Clone)]
+#[repr(C)]
+struct C2RustUnnamed1 {
encoded_lo: u64,
encoded_hi: u64,
}
-
#[derive(Copy, Clone)]
-struct ParsedInstallationId {
+#[repr(C)]
+struct C2RustUnnamed2 {
+ lo: u64,
+ hi: u64,
+}
+#[derive(Copy, Clone)]
+#[repr(C)]
+union C2RustUnnamed3 {
+ buffer: [u8; 14],
+ c2rust_unnamed: C2RustUnnamed2,
+}
+#[derive(Copy, Clone)]
+#[repr(C, packed)]
+struct C2RustUnnamed4 {
hardware_id: u64,
product_id_low: u64,
product_id_high: u8,
key_sha1: u16,
}
-
-static F: [u64; 6] = [
+static mut F: [u64; 6] = [
0,
0x21840136c85381,
0x44197b83892ad0,
@@ -178,7 +201,7 @@ fn residue_sqrt(what: u64) -> u64 {
x
}
-fn find_divisor_v(d: &mut TDivisor) -> i32 {
+unsafe fn find_divisor_v(d: *mut TDivisor) -> i32 {
// u | v^2 - f
// u = u0 + u1*x + x^2
// f%u = f0 + f1*x
@@ -189,8 +212,8 @@ fn find_divisor_v(d: &mut TDivisor) -> i32 {
f2[i as usize] = F[i as usize];
i += 1;
}
- let u0: u64 = d.u[0_i32 as usize];
- let u1: u64 = d.u[1_i32 as usize];
+ let u0: u64 = (*d).u[0_i32 as usize];
+ let u1: u64 = (*d).u[1_i32 as usize];
let mut j: i32 = 4_i32;
loop {
let fresh0 = j;
@@ -258,18 +281,18 @@ fn find_divisor_v(d: &mut TDivisor) -> i32 {
residue_add(f1, residue_mul(u1, residue_mul(v1, v1))),
residue_inv(residue_add(v1, v1)),
);
- d.v[0_i32 as usize] = v0;
- d.v[1_i32 as usize] = v1;
+ (*d).v[0_i32 as usize] = v0;
+ (*d).v[1_i32 as usize] = v1;
1_i32
}
-fn polynomial_mul(
+unsafe fn polynomial_mul(
adeg: i32,
- a: &[u64],
+ a: *const u64,
bdeg: i32,
- b: &[u64],
+ b: *const u64,
mut resultprevdeg: i32,
- result: &mut [u64],
+ result: *mut u64,
) -> i32 {
// generic short slow code
if adeg < 0_i32 || bdeg < 0_i32 {
@@ -277,7 +300,7 @@ fn polynomial_mul(
}
let mut i = resultprevdeg + 1_i32;
while i <= adeg + bdeg {
- result[i as usize] = 0_i32 as u64;
+ *result.offset(i as isize) = 0_i32 as u64;
i += 1;
}
resultprevdeg = i - 1_i32;
@@ -285,79 +308,86 @@ fn polynomial_mul(
while i <= adeg {
let mut j = 0_i32;
while j <= bdeg {
- result[(i + j) as usize] = residue_add(
- result[(i + j) as usize],
- residue_mul(a[i as usize], b[j as usize]),
+ *result.offset((i + j) as isize) = residue_add(
+ *result.offset((i + j) as isize),
+ residue_mul(*a.offset(i as isize), *b.offset(j as isize)),
);
j += 1;
}
i += 1;
}
- while resultprevdeg >= 0_i32 && result[resultprevdeg as usize] == 0_i32 as u64 {
+ while resultprevdeg >= 0_i32 && *result.offset(resultprevdeg as isize) == 0_i32 as u64 {
resultprevdeg -= 1;
}
resultprevdeg
}
-fn polynomial_div_monic(
+unsafe fn polynomial_div_monic(
adeg: i32,
- a: &mut [u64],
+ a: *mut u64,
bdeg: i32,
- b: &[u64],
- mut quotient: Option<&mut [u64]>,
+ b: *const u64,
+ quotient: *mut u64,
) -> i32 {
let mut i = adeg - bdeg;
while i >= 0_i32 {
- let q: u64 = a[(i + bdeg) as usize];
- if let Some(ref mut quotient) = quotient {
- quotient[i as usize] = q;
+ let q: u64 = *a.offset((i + bdeg) as isize);
+ if !quotient.is_null() {
+ *quotient.offset(i as isize) = q;
}
let mut j = 0_i32;
while j < bdeg {
- a[(i + j) as usize] = residue_sub(a[(i + j) as usize], residue_mul(q, b[j as usize]));
+ *a.offset((i + j) as isize) = residue_sub(
+ *a.offset((i + j) as isize),
+ residue_mul(q, *b.offset(j as isize)),
+ );
j += 1;
}
- a[(i + j) as usize] = 0_i32 as u64;
+ *a.offset((i + j) as isize) = 0_i32 as u64;
i -= 1;
}
i += bdeg;
- while i >= 0_i32 && a[i as usize] == 0_i32 as u64 {
+ while i >= 0_i32 && *a.offset(i as isize) == 0_i32 as u64 {
i -= 1;
}
i
}
#[allow(clippy::too_many_arguments)]
-fn polynomial_xgcd(
+unsafe fn polynomial_xgcd(
adeg: i32,
- a: &[u64],
+ a: *const u64,
bdeg: i32,
- b: &[u64],
- pgcddeg: &mut i32,
- gcd: &mut [u64],
- pmult1deg: &mut i32,
- mult1: &mut [u64],
- pmult2deg: &mut i32,
- mult2: &mut [u64],
+ b: *const u64,
+ pgcddeg: *mut i32,
+ gcd: *mut u64,
+ pmult1deg: *mut i32,
+ mult1: *mut u64,
+ pmult2deg: *mut i32,
+ mult2: *mut u64,
) {
let mut sdeg: i32 = -1_i32;
let mut s: [u64; 3] = [0_i32 as u64, 0_i32 as u64, 0_i32 as u64];
let mut mult1deg: i32 = 0_i32;
- mult1[0] = 1_i32 as u64;
- mult1[1] = 0_i32 as u64;
- mult1[2] = 0_i32 as u64;
+ *mult1.offset(0_i32 as isize) = 1_i32 as u64;
+ *mult1.offset(1_i32 as isize) = 0_i32 as u64;
+ *mult1.offset(2_i32 as isize) = 0_i32 as u64;
let mut tdeg: i32 = 0_i32;
let mut t: [u64; 3] = [1_i32 as u64, 0_i32 as u64, 0_i32 as u64];
let mut mult2deg: i32 = -1_i32;
- mult2[0] = 0_i32 as u64;
- mult2[1] = 0_i32 as u64;
- mult2[2] = 0_i32 as u64;
+ *mult2.offset(0_i32 as isize) = 0_i32 as u64;
+ *mult2.offset(1_i32 as isize) = 0_i32 as u64;
+ *mult2.offset(2_i32 as isize) = 0_i32 as u64;
let mut rdeg: i32 = bdeg;
- let mut r: [u64; 3] = [b[0], b[1], b[2]];
+ let mut r: [u64; 3] = [
+ *b.offset(0_i32 as isize),
+ *b.offset(1_i32 as isize),
+ *b.offset(2_i32 as isize),
+ ];
let mut gcddeg: i32 = adeg;
- gcd[0] = a[0];
- gcd[1] = a[1];
- gcd[2] = a[2];
+ *gcd.offset(0_i32 as isize) = *a.offset(0_i32 as isize);
+ *gcd.offset(1_i32 as isize) = *a.offset(1_i32 as isize);
+ *gcd.offset(2_i32 as isize) = *a.offset(2_i32 as isize);
// s*u1 + t*u2 = r
// mult1*u1 + mult2*u2 = gcd
while rdeg >= 0_i32 {
@@ -365,34 +395,55 @@ fn polynomial_xgcd(
let tmp = rdeg as u32;
rdeg = gcddeg;
gcddeg = tmp as i32;
- swap(&mut sdeg, &mut mult1deg);
- swap(&mut tdeg, &mut mult2deg);
- swap(&mut r[0], &mut gcd[0]);
- swap(&mut r[1], &mut gcd[1]);
- swap(&mut r[2], &mut gcd[2]);
- swap(&mut s[0], &mut mult1[0]);
- swap(&mut s[1], &mut mult1[1]);
- swap(&mut s[2], &mut mult1[2]);
- swap(&mut t[0], &mut mult2[0]);
- swap(&mut t[1], &mut mult2[1]);
- swap(&mut t[2], &mut mult2[2]);
+ std::mem::swap(&mut sdeg, &mut mult1deg);
+ std::mem::swap(&mut tdeg, &mut mult2deg);
+ let mut tmp2 = r[0_i32 as usize];
+ r[0_i32 as usize] = *gcd.offset(0_i32 as isize);
+ *gcd.offset(0_i32 as isize) = tmp2;
+ tmp2 = r[1_i32 as usize];
+ r[1_i32 as usize] = *gcd.offset(1_i32 as isize);
+ *gcd.offset(1_i32 as isize) = tmp2;
+ tmp2 = r[2_i32 as usize];
+ r[2_i32 as usize] = *gcd.offset(2_i32 as isize);
+ *gcd.offset(2_i32 as isize) = tmp2;
+ tmp2 = s[0_i32 as usize];
+ s[0_i32 as usize] = *mult1.offset(0_i32 as isize);
+ *mult1.offset(0_i32 as isize) = tmp2;
+ tmp2 = s[1_i32 as usize];
+ s[1_i32 as usize] = *mult1.offset(1_i32 as isize);
+ *mult1.offset(1_i32 as isize) = tmp2;
+ tmp2 = s[2_i32 as usize];
+ s[2_i32 as usize] = *mult1.offset(2_i32 as isize);
+ *mult1.offset(2_i32 as isize) = tmp2;
+ tmp2 = t[0_i32 as usize];
+ t[0_i32 as usize] = *mult2.offset(0_i32 as isize);
+ *mult2.offset(0_i32 as isize) = tmp2;
+ tmp2 = t[1_i32 as usize];
+ t[1_i32 as usize] = *mult2.offset(1_i32 as isize);
+ *mult2.offset(1_i32 as isize) = tmp2;
+ tmp2 = t[2_i32 as usize];
+ t[2_i32 as usize] = *mult2.offset(2_i32 as isize);
+ *mult2.offset(2_i32 as isize) = tmp2;
} else {
let delta: i32 = gcddeg - rdeg;
- let mult: u64 = residue_mul(gcd[gcddeg as usize], residue_inv(r[rdeg as usize]));
+ let mult: u64 =
+ residue_mul(*gcd.offset(gcddeg as isize), residue_inv(r[rdeg as usize]));
// quotient = mult * x**delta
let mut i: i32 = 0_i32;
while i <= rdeg {
- gcd[(i + delta) as usize] =
- residue_sub(gcd[(i + delta) as usize], residue_mul(mult, r[i as usize]));
+ *gcd.offset((i + delta) as isize) = residue_sub(
+ *gcd.offset((i + delta) as isize),
+ residue_mul(mult, r[i as usize]),
+ );
i += 1;
}
- while gcddeg >= 0_i32 && gcd[gcddeg as usize] == 0_i32 as u64 {
+ while gcddeg >= 0_i32 && *gcd.offset(gcddeg as isize) == 0_i32 as u64 {
gcddeg -= 1;
}
let mut i_0: i32 = 0_i32;
while i_0 <= sdeg {
- mult1[(i_0 + delta) as usize] = residue_sub(
- mult1[(i_0 + delta) as usize],
+ *mult1.offset((i_0 + delta) as isize) = residue_sub(
+ *mult1.offset((i_0 + delta) as isize),
residue_mul(mult, s[i_0 as usize]),
);
i_0 += 1;
@@ -400,13 +451,13 @@ fn polynomial_xgcd(
if mult1deg < sdeg + delta {
mult1deg = sdeg + delta;
}
- while mult1deg >= 0_i32 && mult1[mult1deg as usize] == 0_i32 as u64 {
+ while mult1deg >= 0_i32 && *mult1.offset(mult1deg as isize) == 0_i32 as u64 {
mult1deg -= 1;
}
let mut i_1: i32 = 0_i32;
while i_1 <= tdeg {
- mult2[(i_1 + delta) as usize] = residue_sub(
- mult2[(i_1 + delta) as usize],
+ *mult2.offset((i_1 + delta) as isize) = residue_sub(
+ *mult2.offset((i_1 + delta) as isize),
residue_mul(mult, t[i_1 as usize]),
);
i_1 += 1;
@@ -414,7 +465,7 @@ fn polynomial_xgcd(
if mult2deg < tdeg + delta {
mult2deg = tdeg + delta;
}
- while mult2deg >= 0_i32 && mult2[mult2deg as usize] == 0_i32 as u64 {
+ while mult2deg >= 0_i32 && *mult2.offset(mult2deg as isize) == 0_i32 as u64 {
mult2deg -= 1;
}
}
@@ -425,35 +476,35 @@ fn polynomial_xgcd(
*pmult2deg = mult2deg;
}
-fn u2poly(src: &TDivisor, polyu: &mut [u64], polyv: &mut [u64]) -> i32 {
- if src.u[1_i32 as usize] != BAD {
- polyu[0_i32 as usize] = src.u[0_i32 as usize];
- polyu[1_i32 as usize] = src.u[1_i32 as usize];
- polyu[2_i32 as usize] = 1_i32 as u64;
- polyv[0_i32 as usize] = src.v[0_i32 as usize];
- polyv[1_i32 as usize] = src.v[1_i32 as usize];
+unsafe fn u2poly(src: *const TDivisor, polyu: *mut u64, polyv: *mut u64) -> i32 {
+ if (*src).u[1_i32 as usize] != BAD {
+ *polyu.offset(0_i32 as isize) = (*src).u[0_i32 as usize];
+ *polyu.offset(1_i32 as isize) = (*src).u[1_i32 as usize];
+ *polyu.offset(2_i32 as isize) = 1_i32 as u64;
+ *polyv.offset(0_i32 as isize) = (*src).v[0_i32 as usize];
+ *polyv.offset(1_i32 as isize) = (*src).v[1_i32 as usize];
return 2_i32;
}
- if src.u[0_i32 as usize] != BAD {
- polyu[0_i32 as usize] = src.u[0_i32 as usize];
- polyu[1_i32 as usize] = 1_i32 as u64;
- polyv[0_i32 as usize] = src.v[0_i32 as usize];
- polyv[1_i32 as usize] = 0_i32 as u64;
+ if (*src).u[0_i32 as usize] != BAD {
+ *polyu.offset(0_i32 as isize) = (*src).u[0_i32 as usize];
+ *polyu.offset(1_i32 as isize) = 1_i32 as u64;
+ *polyv.offset(0_i32 as isize) = (*src).v[0_i32 as usize];
+ *polyv.offset(1_i32 as isize) = 0_i32 as u64;
return 1_i32;
}
- polyu[0_i32 as usize] = 1_i32 as u64;
- polyv[0_i32 as usize] = 0_i32 as u64;
- polyv[1_i32 as usize] = 0_i32 as u64;
+ *polyu.offset(0_i32 as isize) = 1_i32 as u64;
+ *polyv.offset(0_i32 as isize) = 0_i32 as u64;
+ *polyv.offset(1_i32 as isize) = 0_i32 as u64;
0_i32
}
-fn divisor_add(src1: &TDivisor, src2: &TDivisor, dst: &mut TDivisor) {
+unsafe fn divisor_add(src1: *const TDivisor, src2: *const TDivisor, dst: *mut TDivisor) {
let mut u1: [u64; 3] = [0; 3];
let mut u2: [u64; 3] = [0; 3];
let mut v1: [u64; 2] = [0; 2];
let mut v2: [u64; 2] = [0; 2];
- let u1deg: i32 = u2poly(src1, &mut u1, &mut v1);
- let u2deg: i32 = u2poly(src2, &mut u2, &mut v2);
+ let u1deg: i32 = u2poly(src1, u1.as_mut_ptr(), v1.as_mut_ptr());
+ let u2deg: i32 = u2poly(src2, u2.as_mut_ptr(), v2.as_mut_ptr());
// extended gcd: d1 = gcd(u1, u2) = e1*u1 + e2*u2
let mut d1deg: i32 = 0;
let mut e1deg: i32 = 0;
@@ -462,10 +513,19 @@ fn divisor_add(src1: &TDivisor, src2: &TDivisor, dst: &mut TDivisor) {
let mut e1: [u64; 3] = [0; 3];
let mut e2: [u64; 3] = [0; 3];
polynomial_xgcd(
- u1deg, &u1, u2deg, &u2, &mut d1deg, &mut d1, &mut e1deg, &mut e1, &mut e2deg, &mut e2,
+ u1deg,
+ u1.as_mut_ptr() as *const u64,
+ u2deg,
+ u2.as_mut_ptr() as *const u64,
+ &mut d1deg,
+ d1.as_mut_ptr(),
+ &mut e1deg,
+ e1.as_mut_ptr(),
+ &mut e2deg,
+ e2.as_mut_ptr(),
);
// extended gcd again: d = gcd(d1, v1+v2) = c1*d1 + c2*(v1+v2)
- let b: [u64; 3] = [
+ let mut b: [u64; 3] = [
residue_add(v1[0_i32 as usize], v2[0_i32 as usize]),
residue_add(v1[1_i32 as usize], v2[1_i32 as usize]),
0_i32 as u64,
@@ -486,7 +546,16 @@ fn divisor_add(src1: &TDivisor, src2: &TDivisor, dst: &mut TDivisor) {
let mut c1: [u64; 3] = [0; 3];
let mut c2: [u64; 3] = [0; 3];
polynomial_xgcd(
- d1deg, &d1, bdeg, &b, &mut ddeg, &mut d, &mut c1deg, &mut c1, &mut c2deg, &mut c2,
+ d1deg,
+ d1.as_mut_ptr() as *const u64,
+ bdeg,
+ b.as_mut_ptr() as *const u64,
+ &mut ddeg,
+ d.as_mut_ptr(),
+ &mut c1deg,
+ c1.as_mut_ptr(),
+ &mut c2deg,
+ c2.as_mut_ptr(),
);
let dmult: u64 = residue_inv(d[ddeg as usize]);
let mut i = 0_i32;
@@ -506,7 +575,14 @@ fn divisor_add(src1: &TDivisor, src2: &TDivisor, dst: &mut TDivisor) {
i += 1;
}
let mut u: [u64; 5] = [0; 5];
- let mut udeg: i32 = polynomial_mul(u1deg, &u1, u2deg, &u2, -1_i32, &mut u);
+ let mut udeg: i32 = polynomial_mul(
+ u1deg,
+ u1.as_mut_ptr() as *const u64,
+ u2deg,
+ u2.as_mut_ptr() as *const u64,
+ -1_i32,
+ u.as_mut_ptr(),
+ );
// u is monic
let mut v: [u64; 7] = [0; 7];
let mut tmp: [u64; 7] = [0; 7];
@@ -514,9 +590,30 @@ fn divisor_add(src1: &TDivisor, src2: &TDivisor, dst: &mut TDivisor) {
// c1*(e1*u1*(v2-v1) + d1*v1) + c2*(v1*v2 + f)
v[0_i32 as usize] = residue_sub(v2[0_i32 as usize], v1[0_i32 as usize]);
v[1_i32 as usize] = residue_sub(v2[1_i32 as usize], v1[1_i32 as usize]);
- let mut tmpdeg = polynomial_mul(e1deg, &e1, 1_i32, &v, -1_i32, &mut tmp);
- let mut vdeg = polynomial_mul(u1deg, &u1, tmpdeg, &tmp, -1_i32, &mut v);
- vdeg = polynomial_mul(d1deg, &d1, 1_i32, &v1, vdeg, &mut v);
+ let mut tmpdeg = polynomial_mul(
+ e1deg,
+ e1.as_mut_ptr() as *const u64,
+ 1_i32,
+ v.as_mut_ptr() as *const u64,
+ -1_i32,
+ tmp.as_mut_ptr(),
+ );
+ let mut vdeg = polynomial_mul(
+ u1deg,
+ u1.as_mut_ptr() as *const u64,
+ tmpdeg,
+ tmp.as_mut_ptr() as *const u64,
+ -1_i32,
+ v.as_mut_ptr(),
+ );
+ vdeg = polynomial_mul(
+ d1deg,
+ d1.as_mut_ptr() as *const u64,
+ 1_i32,
+ v1.as_mut_ptr() as *const u64,
+ vdeg,
+ v.as_mut_ptr(),
+ );
i = 0_i32;
while i <= vdeg {
v[i as usize] = residue_mul(v[i as usize], c1[0_i32 as usize]);
@@ -529,26 +626,71 @@ fn divisor_add(src1: &TDivisor, src2: &TDivisor, dst: &mut TDivisor) {
tmp[4] = F[4];
tmp[5] = F[5];
tmpdeg = 5_i32;
- tmpdeg = polynomial_mul(1_i32, &v1, 1_i32, &v2, tmpdeg, &mut tmp);
- vdeg = polynomial_mul(c2deg, &c2, tmpdeg, &tmp, vdeg, &mut v);
+ tmpdeg = polynomial_mul(
+ 1_i32,
+ v1.as_mut_ptr() as *const u64,
+ 1_i32,
+ v2.as_mut_ptr() as *const u64,
+ tmpdeg,
+ tmp.as_mut_ptr(),
+ );
+ vdeg = polynomial_mul(
+ c2deg,
+ c2.as_mut_ptr() as *const u64,
+ tmpdeg,
+ tmp.as_mut_ptr() as *const u64,
+ vdeg,
+ v.as_mut_ptr(),
+ );
if ddeg > 0_i32 {
let mut udiv: [u64; 5] = [0; 5];
- polynomial_div_monic(udeg, &mut u, ddeg, &d, Some(&mut udiv));
+ polynomial_div_monic(
+ udeg,
+ u.as_mut_ptr(),
+ ddeg,
+ d.as_mut_ptr() as *const u64,
+ udiv.as_mut_ptr(),
+ );
udeg -= ddeg;
- polynomial_div_monic(udeg, &mut udiv, ddeg, &d, Some(&mut u));
+ polynomial_div_monic(
+ udeg,
+ udiv.as_mut_ptr(),
+ ddeg,
+ d.as_mut_ptr() as *const u64,
+ u.as_mut_ptr(),
+ );
udeg -= ddeg;
if vdeg >= 0_i32 {
- polynomial_div_monic(vdeg, &mut v, ddeg, &d, Some(&mut udiv));
+ polynomial_div_monic(
+ vdeg,
+ v.as_mut_ptr(),
+ ddeg,
+ d.as_mut_ptr() as *const u64,
+ udiv.as_mut_ptr(),
+ );
vdeg -= ddeg;
for i in 0..=vdeg {
v[i as usize] = udiv[i as usize];
}
}
}
- vdeg = polynomial_div_monic(vdeg, &mut v, udeg, &u, None);
+ vdeg = polynomial_div_monic(
+ vdeg,
+ v.as_mut_ptr(),
+ udeg,
+ u.as_mut_ptr() as *const u64,
+ std::ptr::null_mut::(),
+ );
while udeg > 2_i32 {
// u' = monic((f-v^2)/u), v'=-v mod u'
- tmpdeg = polynomial_mul(vdeg, &v, vdeg, &v, -1_i32, &mut tmp);
+ tmpdeg = polynomial_mul(
+ vdeg,
+ v.as_mut_ptr() as *const u64,
+ vdeg,
+ v.as_mut_ptr() as *const u64,
+ -1_i32,
+ tmp.as_mut_ptr(),
+ );
i = 0_i32;
while i <= tmpdeg && i <= 5_i32 {
tmp[i as usize] = residue_sub(F[i as usize], tmp[i as usize]);
@@ -564,7 +706,13 @@ fn divisor_add(src1: &TDivisor, src2: &TDivisor, dst: &mut TDivisor) {
}
tmpdeg = i - 1_i32;
let mut udiv_0: [u64; 5] = [0; 5];
- polynomial_div_monic(tmpdeg, &mut tmp, udeg, &u, Some(&mut udiv_0));
+ polynomial_div_monic(
+ tmpdeg,
+ tmp.as_mut_ptr(),
+ udeg,
+ u.as_mut_ptr() as *const u64,
+ udiv_0.as_mut_ptr(),
+ );
udeg = tmpdeg - udeg;
let mult: u64 = residue_inv(udiv_0[udeg as usize]);
i = 0_i32;
@@ -578,52 +726,60 @@ fn divisor_add(src1: &TDivisor, src2: &TDivisor, dst: &mut TDivisor) {
v[i as usize] = residue_sub(0_i32 as u64, v[i as usize]);
i += 1;
}
- vdeg = polynomial_div_monic(vdeg, &mut v, udeg, &u, None);
+ vdeg = polynomial_div_monic(
+ vdeg,
+ v.as_mut_ptr(),
+ udeg,
+ u.as_mut_ptr() as *const u64,
+ std::ptr::null_mut::(),
+ );
}
if udeg == 2_i32 {
- dst.u[0_i32 as usize] = u[0_i32 as usize];
- dst.u[1_i32 as usize] = u[1_i32 as usize];
- dst.v[0_i32 as usize] = if vdeg >= 0_i32 {
+ (*dst).u[0_i32 as usize] = u[0_i32 as usize];
+ (*dst).u[1_i32 as usize] = u[1_i32 as usize];
+ (*dst).v[0_i32 as usize] = if vdeg >= 0_i32 {
v[0_i32 as usize]
} else {
0_i32 as u64
};
- dst.v[1_i32 as usize] = if vdeg >= 1_i32 {
+ (*dst).v[1_i32 as usize] = if vdeg >= 1_i32 {
v[1_i32 as usize]
} else {
0_i32 as u64
};
} else if udeg == 1_i32 {
- dst.u[0_i32 as usize] = u[0_i32 as usize];
- dst.u[1_i32 as usize] = BAD;
- dst.v[0_i32 as usize] = if vdeg >= 0_i32 {
+ (*dst).u[0_i32 as usize] = u[0_i32 as usize];
+ (*dst).u[1_i32 as usize] = BAD;
+ (*dst).v[0_i32 as usize] = if vdeg >= 0_i32 {
v[0_i32 as usize]
} else {
0_i32 as u64
};
- dst.v[1_i32 as usize] = BAD;
+ (*dst).v[1_i32 as usize] = BAD;
} else {
- dst.u[0_i32 as usize] = BAD;
- dst.u[1_i32 as usize] = BAD;
- dst.v[0_i32 as usize] = BAD;
- dst.v[1_i32 as usize] = BAD;
+ (*dst).u[0_i32 as usize] = BAD;
+ (*dst).u[1_i32 as usize] = BAD;
+ (*dst).v[0_i32 as usize] = BAD;
+ (*dst).v[1_i32 as usize] = BAD;
};
}
-fn divisor_mul128(src: &TDivisor, mut mult_lo: u64, mut mult_hi: u64, dst: &mut TDivisor) {
+unsafe fn divisor_mul128(
+ src: *const TDivisor,
+ mut mult_lo: u64,
+ mut mult_hi: u64,
+ dst: *mut TDivisor,
+) {
if mult_lo == 0_i32 as u64 && mult_hi == 0_i32 as u64 {
- dst.u[0_i32 as usize] = BAD;
- dst.u[1_i32 as usize] = BAD;
- dst.v[0_i32 as usize] = BAD;
- dst.v[1_i32 as usize] = BAD;
+ (*dst).u[0_i32 as usize] = BAD;
+ (*dst).u[1_i32 as usize] = BAD;
+ (*dst).v[0_i32 as usize] = BAD;
+ (*dst).v[1_i32 as usize] = BAD;
return;
}
let mut cur: TDivisor = *src;
while mult_lo & 1_i32 as u64 == 0 {
- {
- let tmp = cur;
- divisor_add(&tmp, &tmp, &mut cur);
- }
+ divisor_add(&cur, &cur, &mut cur);
mult_lo >>= 1_i32;
if mult_hi & 1_i32 as u64 != 0 {
mult_lo |= 1_u64 << 63_i32;
@@ -640,12 +796,9 @@ fn divisor_mul128(src: &TDivisor, mut mult_lo: u64, mut mult_hi: u64, dst: &mut
if mult_lo == 0_i32 as u64 && mult_hi == 0_i32 as u64 {
break;
}
- {
- let tmp = cur;
- divisor_add(&tmp, &tmp, &mut cur);
- }
+ divisor_add(&cur, &cur, &mut cur);
if mult_lo & 1_i32 as u64 != 0 {
- divisor_add(&(dst.clone()), &cur, dst);
+ divisor_add(dst, &cur, dst);
}
}
}
@@ -654,7 +807,7 @@ fn rol(x: u32, shift: i32) -> u32 {
x << shift | x >> (32_i32 - shift)
}
-fn sha1_single_block(input: &[u8], output: &mut [u8]) {
+unsafe fn sha1_single_block(input: *mut u8, output: *mut u8) {
let mut a = 0x67452301_i32 as u32;
let mut b = 0xefcdab89_u32;
let mut c = 0x98badcfe_u32;
@@ -663,10 +816,10 @@ fn sha1_single_block(input: &[u8], output: &mut [u8]) {
let mut w: [u32; 80] = [0; 80];
let mut i = 0_i32 as usize;
while i < 16 {
- w[i] = ((input[4_usize.wrapping_mul(i)] as i32) << 24_i32
- | (input[4_usize.wrapping_mul(i).wrapping_add(1)] as i32) << 16_i32
- | (input[4_usize.wrapping_mul(i).wrapping_add(2)] as i32) << 8_i32
- | input[4_usize.wrapping_mul(i).wrapping_add(3)] as i32) as u32;
+ w[i] = ((*input.add(4_usize.wrapping_mul(i)) as i32) << 24_i32
+ | (*input.add(4_usize.wrapping_mul(i).wrapping_add(1)) as i32) << 16_i32
+ | (*input.add(4_usize.wrapping_mul(i).wrapping_add(2)) as i32) << 8_i32
+ | *input.add(4_usize.wrapping_mul(i).wrapping_add(3)) as i32) as u32;
i = i.wrapping_add(1);
}
i = 16_i32 as usize;
@@ -741,29 +894,29 @@ fn sha1_single_block(input: &[u8], output: &mut [u8]) {
c = c.wrapping_add(0x98badcfe_u32);
d = d.wrapping_add(0x10325476_i32 as u32);
e = e.wrapping_add(0xc3d2e1f0_u32);
- output[0] = (a >> 24_i32) as u8;
- output[1] = (a >> 16_i32) as u8;
- output[2] = (a >> 8_i32) as u8;
- output[3] = a as u8;
- output[4] = (b >> 24_i32) as u8;
- output[5] = (b >> 16_i32) as u8;
- output[6] = (b >> 8_i32) as u8;
- output[7] = b as u8;
- output[8] = (c >> 24_i32) as u8;
- output[9] = (c >> 16_i32) as u8;
- output[10] = (c >> 8_i32) as u8;
- output[11] = c as u8;
- output[12] = (d >> 24_i32) as u8;
- output[13] = (d >> 16_i32) as u8;
- output[14] = (d >> 8_i32) as u8;
- output[15] = d as u8;
- output[16] = (e >> 24_i32) as u8;
- output[17] = (e >> 16_i32) as u8;
- output[18] = (e >> 8_i32) as u8;
- output[19] = e as u8;
+ *output.offset(0_i32 as isize) = (a >> 24_i32) as u8;
+ *output.offset(1_i32 as isize) = (a >> 16_i32) as u8;
+ *output.offset(2_i32 as isize) = (a >> 8_i32) as u8;
+ *output.offset(3_i32 as isize) = a as u8;
+ *output.offset(4_i32 as isize) = (b >> 24_i32) as u8;
+ *output.offset(5_i32 as isize) = (b >> 16_i32) as u8;
+ *output.offset(6_i32 as isize) = (b >> 8_i32) as u8;
+ *output.offset(7_i32 as isize) = b as u8;
+ *output.offset(8_i32 as isize) = (c >> 24_i32) as u8;
+ *output.offset(9_i32 as isize) = (c >> 16_i32) as u8;
+ *output.offset(10_i32 as isize) = (c >> 8_i32) as u8;
+ *output.offset(11_i32 as isize) = c as u8;
+ *output.offset(12_i32 as isize) = (d >> 24_i32) as u8;
+ *output.offset(13_i32 as isize) = (d >> 16_i32) as u8;
+ *output.offset(14_i32 as isize) = (d >> 8_i32) as u8;
+ *output.offset(15_i32 as isize) = d as u8;
+ *output.offset(16_i32 as isize) = (e >> 24_i32) as u8;
+ *output.offset(17_i32 as isize) = (e >> 16_i32) as u8;
+ *output.offset(18_i32 as isize) = (e >> 8_i32) as u8;
+ *output.offset(19_i32 as isize) = e as u8;
}
-fn mix(buffer: &mut [u8], buf_size: usize, key: &[u8], key_size: usize) {
+unsafe fn mix(buffer: *mut u8, buf_size: usize, key: *const u8, key_size: usize) {
let mut sha1_input: [u8; 64] = [0; 64];
let mut sha1_result: [u8; 20] = [0; 20];
let half: usize = buf_size.wrapping_div(2);
@@ -772,16 +925,22 @@ fn mix(buffer: &mut [u8], buf_size: usize, key: &[u8], key_size: usize) {
for n in &mut sha1_input {
*n = 0;
}
- sha1_input[..half].copy_from_slice(&buffer[half..]);
- sha1_input[half..half.wrapping_add(key_size)].copy_from_slice(key);
+ ptr::copy_nonoverlapping(buffer.add(half), sha1_input.as_mut_ptr(), half);
+ ptr::copy_nonoverlapping(
+ key as *const c_void,
+ sha1_input.as_mut_ptr().add(half) as *mut c_void,
+ key_size,
+ );
sha1_input[half.wrapping_add(key_size)] = 0x80_i32 as u8;
- sha1_input[(size_of::<[u8; 64]>() as u64).wrapping_sub(1_i32 as u64) as usize] =
+ sha1_input
+ [(::std::mem::size_of::<[u8; 64]>() as u64).wrapping_sub(1_i32 as u64) as usize] =
half.wrapping_add(key_size).wrapping_mul(8) as u8;
- sha1_input[(size_of::<[u8; 64]>() as u64).wrapping_sub(2_i32 as u64) as usize] =
+ sha1_input
+ [(::std::mem::size_of::<[u8; 64]>() as u64).wrapping_sub(2_i32 as u64) as usize] =
half.wrapping_add(key_size)
.wrapping_mul(8)
.wrapping_div(0x100) as u8;
- sha1_single_block(&sha1_input, &mut sha1_result);
+ sha1_single_block(sha1_input.as_mut_ptr(), sha1_result.as_mut_ptr());
let mut i = half & !3;
while i < half {
sha1_result[i] = sha1_result[i.wrapping_add(4).wrapping_sub(half & 3)];
@@ -789,16 +948,17 @@ fn mix(buffer: &mut [u8], buf_size: usize, key: &[u8], key_size: usize) {
}
i = 0_i32 as usize;
while i < half {
- let tmp: u8 = buffer[i.wrapping_add(half)];
- buffer[i.wrapping_add(half)] = (buffer[i] as i32 ^ sha1_result[i] as i32) as u8;
- buffer[i] = tmp;
+ let tmp: u8 = *buffer.add(i.wrapping_add(half));
+ *buffer.add(i.wrapping_add(half)) =
+ (*buffer.add(i) as i32 ^ sha1_result[i] as i32) as u8;
+ *buffer.add(i) = tmp;
i = i.wrapping_add(1);
}
external_counter += 1;
}
}
-fn unmix(buffer: &mut [u8], buf_size: usize, key: &[u8], key_size: usize) {
+unsafe fn unmix(buffer: *mut u8, buf_size: usize, key: *const u8, key_size: usize) {
let mut sha1_input: [u8; 64] = [0; 64];
let mut sha1_result: [u8; 20] = [0; 20];
let half: usize = buf_size.wrapping_div(2);
@@ -807,16 +967,18 @@ fn unmix(buffer: &mut [u8], buf_size: usize, key: &[u8], key_size: usize) {
for n in &mut sha1_input {
*n = 0;
}
- sha1_input[..half].copy_from_slice(&buffer[..half]);
- sha1_input[half..half.wrapping_add(key_size)].copy_from_slice(key);
+ ptr::copy_nonoverlapping(buffer, sha1_input.as_mut_ptr(), half);
+ ptr::copy_nonoverlapping(key, sha1_input.as_mut_ptr().add(half), key_size);
sha1_input[half.wrapping_add(key_size)] = 0x80_i32 as u8;
- sha1_input[(size_of::<[u8; 64]>() as u64).wrapping_sub(1_i32 as u64) as usize] =
+ sha1_input
+ [(::std::mem::size_of::<[u8; 64]>() as u64).wrapping_sub(1_i32 as u64) as usize] =
half.wrapping_add(key_size).wrapping_mul(8) as u8;
- sha1_input[(size_of::<[u8; 64]>() as u64).wrapping_sub(2_i32 as u64) as usize] =
+ sha1_input
+ [(::std::mem::size_of::<[u8; 64]>() as u64).wrapping_sub(2_i32 as u64) as usize] =
half.wrapping_add(key_size)
.wrapping_mul(8)
.wrapping_div(0x100) as u8;
- sha1_single_block(&sha1_input, &mut sha1_result);
+ sha1_single_block(sha1_input.as_mut_ptr(), sha1_result.as_mut_ptr());
let mut i = half & !3;
while i < half {
sha1_result[i] = sha1_result[i.wrapping_add(4).wrapping_sub(half & 3)];
@@ -824,29 +986,33 @@ fn unmix(buffer: &mut [u8], buf_size: usize, key: &[u8], key_size: usize) {
}
i = 0_i32 as usize;
while i < half {
- let tmp: u8 = buffer[i];
- buffer[i] = (buffer[i.wrapping_add(half)] as i32 ^ sha1_result[i] as i32) as u8;
- buffer[i.wrapping_add(half)] = tmp;
+ let tmp: u8 = *buffer.add(i);
+ *buffer.add(i) =
+ (*buffer.add(i.wrapping_add(half)) as i32 ^ sha1_result[i] as i32) as u8;
+ *buffer.add(i.wrapping_add(half)) = tmp;
i = i.wrapping_add(1);
}
external_counter += 1;
}
}
-pub fn generate(installation_id_str: &[u8], confirmation_id: &mut [u8]) -> i32 {
+pub unsafe fn generate(installation_id_str: *const i8, confirmation_id: *mut i8) -> i32 {
let mut installation_id: [u8; 19] = [0; 19]; // 10**45 < 256**19
let mut installation_id_len: usize = 0_i32 as usize;
+ let mut p: *const i8 = installation_id_str;
let mut count: usize = 0_i32 as usize;
let mut total_count: usize = 0_i32 as usize;
let mut check: u32 = 0_i32 as u32;
- for p in installation_id_str.iter() {
- let p_curr = *p as i8;
- if !(p_curr as i32 == ' ' as i32 || p_curr as i32 == '-' as i32) {
- let d: i32 = p_curr as i32 - '0' as i32;
+ while *p != 0 {
+ if !(*p as i32 == ' ' as i32 || *p as i32 == '-' as i32) {
+ let d: i32 = *p as i32 - '0' as i32;
if !(0_i32..=9_i32).contains(&d) {
return 3_i32;
}
- if count == 5 {
+ if count == 5 || *p.offset(1_i32 as isize) as i32 == 0_i32 {
+ if count == 0 {
+ return if total_count == 45 { 2_i32 } else { 1_i32 };
+ }
if d as u32 != check.wrapping_rem(7_i32 as u32) {
return if count < 5 { 1_i32 } else { 4_i32 };
}
@@ -880,11 +1046,12 @@ pub fn generate(installation_id_str: &[u8], confirmation_id: &mut [u8]) -> i32 {
}
}
}
+ p = p.offset(1);
}
if total_count != 41 && total_count < 45 {
return 1_i32;
}
- while installation_id_len < size_of::<[u8; 19]>() {
+ while installation_id_len < ::std::mem::size_of::<[u8; 19]>() {
installation_id[installation_id_len] = 0_i32 as u8;
installation_id_len = installation_id_len.wrapping_add(1);
}
@@ -895,32 +1062,25 @@ pub fn generate(installation_id_str: &[u8], confirmation_id: &mut [u8]) -> i32 {
0xd4_i32 as u8,
];
unmix(
- &mut installation_id,
+ installation_id.as_mut_ptr(),
(if total_count == 41 { 17_i32 } else { 19_i32 }) as usize,
- &IID_KEY,
+ IID_KEY.as_ptr(),
4_i32 as usize,
);
if installation_id[18_i32 as usize] as i32 >= 0x10_i32 {
return 5_i32;
}
- let mut parsed = ParsedInstallationId {
+ let mut parsed: C2RustUnnamed4 = C2RustUnnamed4 {
hardware_id: 0,
product_id_low: 0,
product_id_high: 0,
key_sha1: 0,
};
-
- let hardware_id_bytes: [u8; 8] = installation_id[0..8].try_into().unwrap();
- parsed.hardware_id = u64::from_le_bytes(hardware_id_bytes);
-
- let product_id_low_bytes: [u8; 8] = installation_id[8..16].try_into().unwrap();
- parsed.product_id_low = u64::from_le_bytes(product_id_low_bytes);
-
- parsed.product_id_high = installation_id[16];
-
- let key_sha1_bytes: [u8; 2] = installation_id[17..19].try_into().unwrap();
- parsed.key_sha1 = u16::from_le_bytes(key_sha1_bytes);
-
+ ptr::copy_nonoverlapping(
+ installation_id.as_mut_ptr() as *const c_void,
+ &mut parsed as *mut C2RustUnnamed4 as *mut c_void,
+ std::mem::size_of::(),
+ );
let product_id_1: u32 = (parsed.product_id_low & ((1_i32 << 17_i32) - 1_i32) as u64) as u32;
let product_id_2: u32 =
(parsed.product_id_low >> 17_i32 & ((1_i32 << 10_i32) - 1_i32) as u64) as u32;
@@ -933,33 +1093,39 @@ pub fn generate(installation_id_str: &[u8], confirmation_id: &mut [u8]) -> i32 {
return 5_i32;
}
let mut keybuf: [u8; 16] = [0; 16];
- keybuf[..8].copy_from_slice(&parsed.hardware_id.to_le_bytes()[..8]);
- let product_id_mixed: u64 = (product_id_1 as u64) << 41_i32
+ let mut hardware_id = parsed.hardware_id;
+ ptr::copy_nonoverlapping(
+ &mut hardware_id as *mut u64 as *const c_void,
+ keybuf.as_mut_ptr() as *mut c_void,
+ 8,
+ );
+ let mut product_id_mixed: u64 = (product_id_1 as u64) << 41_i32
| (product_id_2 as u64) << 58_i32
| (product_id_3 as u64) << 17_i32
| product_id_4 as u64;
- keybuf[8..16].copy_from_slice(&product_id_mixed.to_le_bytes()[..8]);
+ ptr::copy_nonoverlapping(
+ &mut product_id_mixed as *mut u64 as *const c_void,
+ keybuf.as_mut_ptr().offset(8) as *mut c_void,
+ 8,
+ );
let mut d_0: TDivisor = TDivisor {
u: [0; 2],
v: [0; 2],
};
let mut attempt = 0_i32 as u8;
while attempt as i32 <= 0x80_i32 {
- let mut u: [u8; 14] = [0; 14];
- u[7_i32 as usize] = attempt;
- mix(&mut u, 14_i32 as usize, &keybuf, 16_i32 as usize);
- let u_lo = u64::from_le_bytes(u[0..8].try_into().unwrap());
- let u_hi = u64::from_le_bytes(
- u[8..14]
- .iter()
- .chain([0, 0].iter())
- .cloned()
- .collect::>()[..]
- .try_into()
- .unwrap(),
+ let mut u: C2RustUnnamed3 = C2RustUnnamed3 { buffer: [0; 14] };
+ u.c2rust_unnamed.lo = 0_i32 as u64;
+ u.c2rust_unnamed.hi = 0_i32 as u64;
+ u.buffer[7_i32 as usize] = attempt;
+ mix(
+ (u.buffer).as_mut_ptr(),
+ 14_i32 as usize,
+ keybuf.as_mut_ptr(),
+ 16_i32 as usize,
);
- let mut x2: u64 = ui128_quotient_mod(u_lo, u_hi);
- let x1: u64 = u_lo.wrapping_sub(x2.wrapping_mul(MOD));
+ let mut x2: u64 = ui128_quotient_mod(u.c2rust_unnamed.lo, u.c2rust_unnamed.hi);
+ let x1: u64 = u.c2rust_unnamed.lo.wrapping_sub(x2.wrapping_mul(MOD));
x2 = x2.wrapping_add(1);
d_0.u[0_i32 as usize] = residue_sub(
residue_mul(x1, x1),
@@ -975,28 +1141,35 @@ pub fn generate(installation_id_str: &[u8], confirmation_id: &mut [u8]) -> i32 {
return 6_i32;
}
divisor_mul128(
- &(d_0.clone()),
+ &d_0,
0x4e21b9d10f127c1_i64 as u64,
0x40da7c36d44c_i64 as u64,
&mut d_0,
);
- let mut e = Encoded {
- encoded_lo: 0,
- encoded_hi: 0,
+ let mut e: C2RustUnnamed0 = C2RustUnnamed0 {
+ c2rust_unnamed: C2RustUnnamed1 {
+ encoded_lo: 0,
+ encoded_hi: 0,
+ },
};
if d_0.u[0_i32 as usize] == BAD {
// we can not get the zero divisor, actually...
- e.encoded_lo = umul128(MOD.wrapping_add(2_i32 as u64), MOD, &mut e.encoded_hi);
+ e.c2rust_unnamed.encoded_lo = umul128(
+ MOD.wrapping_add(2_i32 as u64),
+ MOD,
+ &mut e.c2rust_unnamed.encoded_hi,
+ );
} else if d_0.u[1_i32 as usize] == BAD {
- e.encoded_lo = umul128(
+ e.c2rust_unnamed.encoded_lo = umul128(
MOD.wrapping_add(1_i32 as u64),
d_0.u[0_i32 as usize],
- &mut e.encoded_hi,
+ &mut e.c2rust_unnamed.encoded_hi,
);
- e.encoded_lo = e.encoded_lo.wrapping_add(MOD);
- e.encoded_hi = e
+ e.c2rust_unnamed.encoded_lo = e.c2rust_unnamed.encoded_lo.wrapping_add(MOD);
+ e.c2rust_unnamed.encoded_hi = e
+ .c2rust_unnamed
.encoded_hi
- .wrapping_add((e.encoded_lo < MOD) as i32 as u64);
+ .wrapping_add((e.c2rust_unnamed.encoded_lo < MOD) as i32 as u64);
} else {
let x1_0: u64 = (if d_0.u[1_i32 as usize] as i32 % 2_i32 != 0 {
d_0.u[1_i32 as usize].wrapping_add(MOD)
@@ -1008,15 +1181,16 @@ pub fn generate(installation_id_str: &[u8], confirmation_id: &mut [u8]) -> i32 {
let mut x2_0: u64 = residue_sqrt(x2sqr);
if x2_0 == BAD {
x2_0 = residue_sqrt(residue_mul(x2sqr, residue_inv(43_i32 as u64)));
- e.encoded_lo = umul128(
+ e.c2rust_unnamed.encoded_lo = umul128(
MOD.wrapping_add(1_i32 as u64),
MOD.wrapping_add(x2_0),
- &mut e.encoded_hi,
+ &mut e.c2rust_unnamed.encoded_hi,
);
- e.encoded_lo = e.encoded_lo.wrapping_add(x1_0);
- e.encoded_hi = e
+ e.c2rust_unnamed.encoded_lo = e.c2rust_unnamed.encoded_lo.wrapping_add(x1_0);
+ e.c2rust_unnamed.encoded_hi = e
+ .c2rust_unnamed
.encoded_hi
- .wrapping_add((e.encoded_lo < x1_0) as i32 as u64);
+ .wrapping_add((e.c2rust_unnamed.encoded_lo < x1_0) as i32 as u64);
} else {
// points (-x1+x2, v(-x1+x2)) and (-x1-x2, v(-x1-x2))
let mut x1a: u64 = residue_sub(x1_0, x2_0);
@@ -1030,67 +1204,72 @@ pub fn generate(installation_id_str: &[u8], confirmation_id: &mut [u8]) -> i32 {
residue_mul(d_0.v[1_i32 as usize], x2a),
);
if x1a > x2a {
- swap(&mut x1a, &mut x2a);
+ std::mem::swap(&mut x1a, &mut x2a);
}
if (y1 ^ y2) & 1_i32 as u64 != 0 {
- swap(&mut x1a, &mut x2a);
+ std::mem::swap(&mut x1a, &mut x2a);
}
- e.encoded_lo = umul128(MOD.wrapping_add(1_i32 as u64), x1a, &mut e.encoded_hi);
- e.encoded_lo = e.encoded_lo.wrapping_add(x2a);
- e.encoded_hi = e
+ e.c2rust_unnamed.encoded_lo = umul128(
+ MOD.wrapping_add(1_i32 as u64),
+ x1a,
+ &mut e.c2rust_unnamed.encoded_hi,
+ );
+ e.c2rust_unnamed.encoded_lo = e.c2rust_unnamed.encoded_lo.wrapping_add(x2a);
+ e.c2rust_unnamed.encoded_hi = e
+ .c2rust_unnamed
.encoded_hi
- .wrapping_add((e.encoded_lo < x2a) as i32 as u64);
+ .wrapping_add((e.c2rust_unnamed.encoded_lo < x2a) as i32 as u64);
}
}
- let mut e_2 = [
- u32::from_le_bytes(e.encoded_lo.to_le_bytes()[0..4].try_into().unwrap()),
- u32::from_le_bytes(e.encoded_lo.to_le_bytes()[4..].try_into().unwrap()),
- u32::from_le_bytes(e.encoded_hi.to_le_bytes()[0..4].try_into().unwrap()),
- u32::from_le_bytes(e.encoded_hi.to_le_bytes()[4..].try_into().unwrap()),
- ];
let mut decimal: [u8; 35] = [0; 35];
let mut i = 0_i32 as usize;
while i < 35 {
- let c: u32 = (e_2[3_i32 as usize]).wrapping_rem(10_i32 as u32);
- e_2[3_i32 as usize] = e_2[3_i32 as usize].wrapping_div(10_i32 as u32);
- let c2: u32 =
- ((c as u64) << 32_i32 | e_2[2_i32 as usize] as u64).wrapping_rem(10_i32 as u64) as u32;
- e_2[2_i32 as usize] =
- ((c as u64) << 32_i32 | e_2[2_i32 as usize] as u64).wrapping_div(10_i32 as u64) as u32;
- let c3: u32 =
- ((c2 as u64) << 32_i32 | e_2[1_i32 as usize] as u64).wrapping_rem(10_i32 as u64) as u32;
- e_2[1_i32 as usize] =
- ((c2 as u64) << 32_i32 | e_2[1_i32 as usize] as u64).wrapping_div(10_i32 as u64) as u32;
- let c4: u32 =
- ((c3 as u64) << 32_i32 | e_2[0_i32 as usize] as u64).wrapping_rem(10_i32 as u64) as u32;
- e_2[0_i32 as usize] =
- ((c3 as u64) << 32_i32 | e_2[0_i32 as usize] as u64).wrapping_div(10_i32 as u64) as u32;
+ let c: u32 = (e.c2rust_unnamed_0.encoded[3_i32 as usize]).wrapping_rem(10_i32 as u32);
+ e.c2rust_unnamed_0.encoded[3_i32 as usize] =
+ e.c2rust_unnamed_0.encoded[3_i32 as usize].wrapping_div(10_i32 as u32);
+ let c2: u32 = ((c as u64) << 32_i32 | e.c2rust_unnamed_0.encoded[2_i32 as usize] as u64)
+ .wrapping_rem(10_i32 as u64) as u32;
+ e.c2rust_unnamed_0.encoded[2_i32 as usize] =
+ ((c as u64) << 32_i32 | e.c2rust_unnamed_0.encoded[2_i32 as usize] as u64)
+ .wrapping_div(10_i32 as u64) as u32;
+ let c3: u32 = ((c2 as u64) << 32_i32 | e.c2rust_unnamed_0.encoded[1_i32 as usize] as u64)
+ .wrapping_rem(10_i32 as u64) as u32;
+ e.c2rust_unnamed_0.encoded[1_i32 as usize] =
+ ((c2 as u64) << 32_i32 | e.c2rust_unnamed_0.encoded[1_i32 as usize] as u64)
+ .wrapping_div(10_i32 as u64) as u32;
+ let c4: u32 = ((c3 as u64) << 32_i32 | e.c2rust_unnamed_0.encoded[0_i32 as usize] as u64)
+ .wrapping_rem(10_i32 as u64) as u32;
+ e.c2rust_unnamed_0.encoded[0_i32 as usize] =
+ ((c3 as u64) << 32_i32 | e.c2rust_unnamed_0.encoded[0_i32 as usize] as u64)
+ .wrapping_div(10_i32 as u64) as u32;
decimal[34_usize.wrapping_sub(i)] = c4 as u8;
i = i.wrapping_add(1);
}
- let q = confirmation_id;
- let mut i: usize = 0;
- let mut q_i = 0;
+ let mut q: *mut i8 = confirmation_id;
+ i = 0_i32 as usize;
while i < 7 {
if i != 0 {
- q[q_i] = b'-';
- q_i += 1;
+ let fresh2 = q;
+ q = q.offset(1);
+ *fresh2 = '-' as i32 as i8;
}
- let p_0: &mut [u8] = &mut decimal[i.wrapping_mul(5)..];
- q[q_i] = (p_0[0] as i32 + '0' as i32) as u8;
- q[q_i + 1] = (p_0[1] as i32 + '0' as i32) as u8;
- q[q_i + 2] = (p_0[2] as i32 + '0' as i32) as u8;
- q[q_i + 3] = (p_0[3] as i32 + '0' as i32) as u8;
- q[q_i + 4] = (p_0[4] as i32 + '0' as i32) as u8;
- q[q_i + 5] = ((p_0[0] as i32
- + p_0[1] as i32 * 2_i32
- + p_0[2] as i32
- + p_0[3] as i32 * 2_i32
- + p_0[4] as i32)
+ let p_0: *mut u8 = decimal.as_mut_ptr().add(i.wrapping_mul(5));
+ *q.offset(0_i32 as isize) = (*p_0.offset(0_i32 as isize) as i32 + '0' as i32) as i8;
+ *q.offset(1_i32 as isize) = (*p_0.offset(1_i32 as isize) as i32 + '0' as i32) as i8;
+ *q.offset(2_i32 as isize) = (*p_0.offset(2_i32 as isize) as i32 + '0' as i32) as i8;
+ *q.offset(3_i32 as isize) = (*p_0.offset(3_i32 as isize) as i32 + '0' as i32) as i8;
+ *q.offset(4_i32 as isize) = (*p_0.offset(4_i32 as isize) as i32 + '0' as i32) as i8;
+ *q.offset(5_i32 as isize) = ((*p_0.offset(0_i32 as isize) as i32
+ + *p_0.offset(1_i32 as isize) as i32 * 2_i32
+ + *p_0.offset(2_i32 as isize) as i32
+ + *p_0.offset(3_i32 as isize) as i32 * 2_i32
+ + *p_0.offset(4_i32 as isize) as i32)
% 7_i32
- + '0' as i32) as u8;
- q_i = q_i.wrapping_add(6);
+ + '0' as i32) as i8;
+ q = q.offset(6_i32 as isize);
i = i.wrapping_add(1);
}
+ let fresh3 = q.offset(1);
+ *fresh3 = 0_i32 as i8;
0_i32
}
diff --git a/umskt/src/confid/mod.rs b/umskt/src/confid/mod.rs
index 4b81a92..077c2f5 100644
--- a/umskt/src/confid/mod.rs
+++ b/umskt/src/confid/mod.rs
@@ -1,13 +1,5 @@
-//! Code to generate a Confirmation ID for a given Installation ID
-//!
-//! ## History
-//! The algorithm this uses was originally provided to the UMSKT project by diamondggg.
-//! The history provided by diamondggg is that they are the originator of the code
-//! and was created in tandem with an acquaintance who knows number theory.
-//! The file dates suggest this code was written sometime in 2017/2018.
-//!
-//! The Rust version of the code was created by running the original through C2Rust
-//! and then manually fixing up the result.
+use std::ffi::{CStr, CString};
+
use thiserror::Error;
mod black_box;
@@ -28,10 +20,6 @@ pub enum ConfirmationIdError {
Unlucky,
}
-/// Generates a confirmation ID from the given installation ID
-///
-/// # Arguments
-/// * `installation_id` - A string with 7 groups of 6 digits, with or without hyphens
pub fn generate(installation_id: &str) -> Result {
if installation_id.len() < 54 {
return Err(ConfirmationIdError::TooShort);
@@ -39,9 +27,9 @@ pub fn generate(installation_id: &str) -> Result {
if installation_id.len() > 54 {
return Err(ConfirmationIdError::TooLarge);
}
- let inst_id = installation_id.as_bytes();
- let mut conf_id = [0u8; 48];
- let result = black_box::generate(inst_id, &mut conf_id);
+ let inst_id = CString::new(installation_id).unwrap();
+ let conf_id = [0u8; 49];
+ let result = unsafe { black_box::generate(inst_id.as_ptr(), conf_id.as_ptr() as *mut i8) };
match result {
0 => {}
1 => return Err(ConfirmationIdError::TooShort),
@@ -52,7 +40,12 @@ pub fn generate(installation_id: &str) -> Result {
6 => return Err(ConfirmationIdError::Unlucky),
_ => panic!("Unknown error code: {}", result),
}
- Ok(String::from_utf8_lossy(&conf_id).into())
+ unsafe {
+ Ok(CStr::from_ptr(conf_id.as_ptr() as *const i8)
+ .to_str()
+ .unwrap()
+ .to_string())
+ }
}
#[cfg(test)]
diff --git a/umskt/src/crypto.rs b/umskt/src/crypto.rs
index 5ad2491..831971a 100644
--- a/umskt/src/crypto.rs
+++ b/umskt/src/crypto.rs
@@ -1,42 +1,24 @@
-//! Code that deals with elliptic curve cryptography
use anyhow::Result;
-use num_bigint::BigInt;
-use num_integer::Integer;
-use num_traits::{Num, One, Zero};
+use openssl::{
+ bn::{BigNum, BigNumContext},
+ ec::{EcGroup, EcPoint},
+};
-/// Represents a point (possibly) on an elliptic curve.
-///
-/// This is either the point at infinity, or a point with affine coordinates `x` and `y`.
-/// It is not guaranteed to be on the curve.
-#[derive(Debug, Clone, PartialEq, Eq)]
-pub enum Point {
- Infinity,
- Point { x: BigInt, y: BigInt },
-}
-
-/// Represents an elliptic curve of the form `y^2 = x^3 + ax + b (mod p)`
-///
-/// `b` is not used in any of the calculations, so is not stored.
-///
-/// This implements all the necessary elliptic curve arithmetic for verifying and generating
-/// product keys.
pub struct EllipticCurve {
- a: BigInt,
- p: BigInt,
- pub gen_point: Point,
- pub pub_point: Point,
+ pub curve: EcGroup,
+ pub gen_point: EcPoint,
+ pub pub_point: EcPoint,
}
-/// Stores the additional data necessary to generate product keys.
pub struct PrivateKey {
- pub gen_order: BigInt,
- pub private_key: BigInt,
+ pub gen_order: BigNum,
+ pub private_key: BigNum,
}
impl PrivateKey {
pub fn new(gen_order: &str, private_key: &str) -> Result {
- let gen_order = BigInt::from_str_radix(gen_order, 10)?;
- let private_key = BigInt::from_str_radix(private_key, 10)?;
+ let gen_order = BigNum::from_dec_str(gen_order)?;
+ let private_key = &gen_order - &BigNum::from_dec_str(private_key)?;
Ok(Self {
gen_order,
private_key,
@@ -45,179 +27,37 @@ impl PrivateKey {
}
impl EllipticCurve {
- /// Creates a new elliptic curve from the given parameters. `b` is not necessary.
pub fn new(
p: &str,
a: &str,
+ b: &str,
generator_x: &str,
generator_y: &str,
public_key_x: &str,
public_key_y: &str,
) -> Result {
- let p = BigInt::from_str_radix(p, 10)?;
- 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 mut context = BigNumContext::new()?;
- let gen_point = Point::Point {
- x: generator_x,
- y: generator_y,
- };
+ 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 pub_point = Point::Point {
- x: public_key_x,
- y: public_key_y,
- };
+ let curve = EcGroup::from_components(p, a, b, &mut context)?;
+
+ let mut gen_point = EcPoint::new(&curve)?;
+ gen_point.set_affine_coordinates_gfp(&curve, &generator_x, &generator_y, &mut context)?;
+
+ let mut pub_point = EcPoint::new(&curve)?;
+ pub_point.set_affine_coordinates_gfp(&curve, &public_key_x, &public_key_y, &mut context)?;
Ok(Self {
- a,
- p,
+ curve,
gen_point,
pub_point,
})
}
-
- 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,
- }
- }
-
- /// Adds two points on the curve together.
- ///
- /// If the points are the same, it doubles the point.
- ///
- /// If one of the points is the point at infinity, it returns the other point.
- ///
- /// If both points are the point at infinity, it returns the point at infinity.
- pub(crate) 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,
- }
- }
-
- /// Multiplies a point by a scalar.
- ///
- /// Uses the double-and-add algorithm.
- pub(crate) 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
- }
-}
-
-/// Calculates the legendre symbol of `p`: `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)
-}
-
-/// Calculates the modular square root of `n` such that `result^2 = n (mod p)`
-/// using the Tonelli-Shanks algorithm. Returns `None` if `p` is not prime.
-///
-/// # Arguments
-///
-/// * `n` - The number to find the square root of
-/// * `p` - The prime modulus (_must_ be prime)
-pub(crate) fn mod_sqrt(n: &BigInt, p: &BigInt) -> Option {
- 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;
- }
}
diff --git a/umskt/src/key.rs b/umskt/src/key.rs
index 4dd8b2d..562a8a2 100644
--- a/umskt/src/key.rs
+++ b/umskt/src/key.rs
@@ -1,9 +1,7 @@
use std::collections::VecDeque;
use anyhow::{anyhow, Result};
-use num_bigint::{BigInt, Sign};
-use num_integer::Integer;
-use num_traits::{ToPrimitive, Zero};
+use openssl::bn::BigNum;
const PK_LENGTH: usize = 25;
@@ -19,24 +17,20 @@ pub(crate) fn base24_decode(cd_key: &str) -> Result> {
.filter_map(|c| KEY_CHARSET.iter().position(|&x| x == c).map(|i| i as u8))
.collect();
- let mut y = BigInt::zero();
+ let mut y = BigNum::from_u32(0).unwrap();
for i in decoded_key {
- y *= PK_LENGTH - 1;
- y += i as u32;
+ y.mul_word((PK_LENGTH - 1) as u32).unwrap();
+ 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 {
- let mut z = BigInt::from_bytes_be(Sign::Plus, byte_seq);
+ let mut z = BigNum::from_slice(byte_seq).unwrap();
let mut out: VecDeque = VecDeque::new();
- (0..=24).for_each(|_| {
- let (quo, rem) = z.div_rem(&BigInt::from(24));
- z = quo;
- out.push_front(KEY_CHARSET[rem.to_u32().unwrap() as usize]);
- });
+ (0..=24).for_each(|_| out.push_front(KEY_CHARSET[z.div_word(24).unwrap() as usize]));
Ok(out.iter().collect())
}
diff --git a/umskt/src/lib.rs b/umskt/src/lib.rs
index 1a1a8ca..2910152 100644
--- a/umskt/src/lib.rs
+++ b/umskt/src/lib.rs
@@ -1,13 +1,3 @@
-//! # Universal MS Key Toolkit (UMSKT) Rust Edition Rust Edition
-//!
-//! This is an unofficial Rust port of the [UMSKT project](https://github.com/UMSKT/UMSKT/).
-//! It is a pure Rust implementation rather than a binding, so it does not require any C or
-//! C++ dependencies and can be built for any platform supported by Rust and `std`.
-//!
-//! It does not include the required `keys.json` file used by UMSKT. That needs to be found elsewhere.
-//!
-//! See `README.md` for more information.
-//!
pub mod bink1998;
pub mod bink2002;
pub mod confid;
diff --git a/mskey/Cargo.toml b/xpkey/Cargo.toml
similarity index 77%
rename from mskey/Cargo.toml
rename to xpkey/Cargo.toml
index 7f5325a..16d7f27 100644
--- a/mskey/Cargo.toml
+++ b/xpkey/Cargo.toml
@@ -1,8 +1,14 @@
[package]
-name = "mskey"
+name = "xpkey"
version = "0.1.0"
edition = "2021"
+[profile.release]
+strip = true
+opt-level = "z"
+lto = true
+codegen-units = 1
+
[dependencies]
umskt = { path = "../umskt" }
anyhow = "1.0.71"
diff --git a/mskey/src/cli.rs b/xpkey/src/cli.rs
similarity index 100%
rename from mskey/src/cli.rs
rename to xpkey/src/cli.rs
diff --git a/mskey/src/keys.rs b/xpkey/src/keys.rs
similarity index 100%
rename from mskey/src/keys.rs
rename to xpkey/src/keys.rs
diff --git a/mskey/src/main.rs b/xpkey/src/main.rs
similarity index 98%
rename from mskey/src/main.rs
rename to xpkey/src/main.rs
index 600b8fd..f9e709e 100644
--- a/mskey/src/main.rs
+++ b/xpkey/src/main.rs
@@ -102,6 +102,7 @@ fn validate(args: &ValidateArgs) -> Result<()> {
fn initialize_curve(bink: &Bink, bink_id: &str) -> Result {
let p = &bink.p;
let a = &bink.a;
+ let b = &bink.b;
let gx = &bink.g.x;
let gy = &bink.g.y;
let kx = &bink.public.x;
@@ -109,7 +110,7 @@ fn initialize_curve(bink: &Bink, bink_id: &str) -> Result {
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(