mirror of
https://github.com/nab138/isideload.git
synced 2026-03-02 14:36:16 +01:00
first commit
This commit is contained in:
41
apple-private-apis/icloud-auth/rustcrypto-srp/CHANGELOG.md
Normal file
41
apple-private-apis/icloud-auth/rustcrypto-srp/CHANGELOG.md
Normal file
@@ -0,0 +1,41 @@
|
||||
# Changelog
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## 0.6.0 (2022-01-22)
|
||||
### Changed
|
||||
- Use `modpow` for constant time modular exponentiation ([#78])
|
||||
- Rebuild library ([#79])
|
||||
|
||||
[#78]: https://github.com/RustCrypto/PAKEs/pull/78
|
||||
[#79]: https://github.com/RustCrypto/PAKEs/pull/79
|
||||
|
||||
## 0.5.0 (2020-10-07)
|
||||
|
||||
## 0.4.3 (2019-11-07)
|
||||
|
||||
## 0.4.2 (2019-11-06)
|
||||
|
||||
## 0.4.1 (2019-11-07)
|
||||
|
||||
## 0.4.0 (2018-12-20)
|
||||
|
||||
## 0.3.0 (2018-10-22)
|
||||
|
||||
## 0.2.5 (2018-04-14)
|
||||
|
||||
## 0.2.4 (2017-11-01)
|
||||
|
||||
## 0.2.3 (2017-08-17)
|
||||
|
||||
## 0.2.2 (2017-08-14)
|
||||
|
||||
## 0.2.1 (2017-08-14)
|
||||
|
||||
## 0.2.0 (2017-08-14)
|
||||
|
||||
## 0.1.1 (2017-08-13)
|
||||
|
||||
## 0.1.0 (2017-08-13)
|
||||
28
apple-private-apis/icloud-auth/rustcrypto-srp/Cargo.toml
Normal file
28
apple-private-apis/icloud-auth/rustcrypto-srp/Cargo.toml
Normal file
@@ -0,0 +1,28 @@
|
||||
[package]
|
||||
name = "srp"
|
||||
version = "0.6.0"
|
||||
authors = ["RustCrypto Developers"]
|
||||
license = "MIT OR Apache-2.0"
|
||||
description = "Secure Remote Password (SRP) protocol implementation"
|
||||
documentation = "https://docs.rs/srp"
|
||||
repository = "https://github.com/RustCrypto/PAKEs"
|
||||
keywords = ["crypto", "pake", "authentication"]
|
||||
categories = ["cryptography", "authentication"]
|
||||
readme = "README.md"
|
||||
edition = "2021"
|
||||
rust-version = "1.56"
|
||||
|
||||
[dependencies]
|
||||
num-bigint = "0.4"
|
||||
generic-array = "0.14"
|
||||
digest = "0.10"
|
||||
lazy_static = "1.2"
|
||||
subtle = "2.4"
|
||||
base64 = "0.21.0"
|
||||
|
||||
[dev-dependencies]
|
||||
hex-literal = "0.3"
|
||||
num-traits = "0.2"
|
||||
rand = "0.8"
|
||||
sha1 = "0.10.6"
|
||||
sha2 = "0.10.8"
|
||||
201
apple-private-apis/icloud-auth/rustcrypto-srp/LICENSE-APACHE
Normal file
201
apple-private-apis/icloud-auth/rustcrypto-srp/LICENSE-APACHE
Normal file
@@ -0,0 +1,201 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
25
apple-private-apis/icloud-auth/rustcrypto-srp/LICENSE-MIT
Normal file
25
apple-private-apis/icloud-auth/rustcrypto-srp/LICENSE-MIT
Normal file
@@ -0,0 +1,25 @@
|
||||
Copyright (c) 2017 Artyom Pavlov
|
||||
|
||||
Permission is hereby granted, free of charge, to any
|
||||
person obtaining a copy of this software and associated
|
||||
documentation files (the "Software"), to deal in the
|
||||
Software without restriction, including without
|
||||
limitation the rights to use, copy, modify, merge,
|
||||
publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software
|
||||
is furnished to do so, subject to the following
|
||||
conditions:
|
||||
|
||||
The above copyright notice and this permission notice
|
||||
shall be included in all copies or substantial portions
|
||||
of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
|
||||
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
73
apple-private-apis/icloud-auth/rustcrypto-srp/README.md
Normal file
73
apple-private-apis/icloud-auth/rustcrypto-srp/README.md
Normal file
@@ -0,0 +1,73 @@
|
||||
# [RustCrypto]: SRP
|
||||
|
||||
[![crate][crate-image]][crate-link]
|
||||
[![Docs][docs-image]][docs-link]
|
||||
![Apache2/MIT licensed][license-image]
|
||||
![Rust Version][rustc-image]
|
||||
[![Project Chat][chat-image]][chat-link]
|
||||
[![Build Status][build-image]][build-link]
|
||||
|
||||
Pure Rust implementation of the [Secure Remote Password] password-authenticated
|
||||
key-exchange algorithm.
|
||||
|
||||
[Documentation][docs-link]
|
||||
|
||||
## About
|
||||
|
||||
This implementation is generic over hash functions using the [`Digest`] trait,
|
||||
so you will need to choose a hash function, e.g. `Sha256` from [`sha2`] crate.
|
||||
|
||||
Additionally this crate allows to use a specialized password hashing
|
||||
algorithm for private key computation instead of method described in the
|
||||
SRP literature.
|
||||
|
||||
Compatibility with other implementations has not yet been tested.
|
||||
|
||||
## ⚠️ Security Warning
|
||||
|
||||
This crate has never received an independent third party audit for security and
|
||||
correctness.
|
||||
|
||||
USE AT YOUR OWN RISK!
|
||||
|
||||
## Minimum Supported Rust Version
|
||||
|
||||
Rust **1.56** or higher.
|
||||
|
||||
Minimum supported Rust version can be changed in the future, but it will be
|
||||
done with a minor version bump.
|
||||
|
||||
## License
|
||||
|
||||
Licensed under either of:
|
||||
|
||||
* [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0)
|
||||
* [MIT license](http://opensource.org/licenses/MIT)
|
||||
|
||||
at your option.
|
||||
|
||||
### Contribution
|
||||
|
||||
Unless you explicitly state otherwise, any contribution intentionally submitted
|
||||
for inclusion in the work by you, as defined in the Apache-2.0 license, shall be
|
||||
dual licensed as above, without any additional terms or conditions.
|
||||
|
||||
[//]: # (badges)
|
||||
|
||||
[crate-image]: https://img.shields.io/crates/v/srp.svg
|
||||
[crate-link]: https://crates.io/crates/srp
|
||||
[docs-image]: https://docs.rs/srp/badge.svg
|
||||
[docs-link]: https://docs.rs/srp/
|
||||
[license-image]: https://img.shields.io/badge/license-Apache2.0/MIT-blue.svg
|
||||
[rustc-image]: https://img.shields.io/badge/rustc-1.56+-blue.svg
|
||||
[chat-image]: https://img.shields.io/badge/zulip-join_chat-blue.svg
|
||||
[chat-link]: https://rustcrypto.zulipchat.com/#narrow/stream/260045-PAKEs
|
||||
[build-image]: https://github.com/RustCrypto/PAKEs/actions/workflows/srp.yml/badge.svg
|
||||
[build-link]: https://github.com/RustCrypto/PAKEs/actions/workflows/srp.yml
|
||||
|
||||
[//]: # (general links)
|
||||
|
||||
[RustCrypto]: https://github.com/RustCrypto
|
||||
[Secure Remote Password]: https://en.wikipedia.org/wiki/Secure_Remote_Password_protocol
|
||||
[`Digest`]: https://docs.rs/digest
|
||||
[`sha2`]: https://crates.io/crates/sha2
|
||||
248
apple-private-apis/icloud-auth/rustcrypto-srp/src/client.rs
Normal file
248
apple-private-apis/icloud-auth/rustcrypto-srp/src/client.rs
Normal file
@@ -0,0 +1,248 @@
|
||||
//! SRP client implementation.
|
||||
//!
|
||||
//! # Usage
|
||||
//! First create SRP client struct by passing to it SRP parameters (shared
|
||||
//! between client and server).
|
||||
//!
|
||||
//! You can use SHA1 from SRP-6a, but it's highly recommended to use specialized
|
||||
//! password hashing algorithm instead (e.g. PBKDF2, argon2 or scrypt).
|
||||
//!
|
||||
//! ```rust
|
||||
//! use crate::srp::groups::G_2048;
|
||||
//! use sha2::Sha256; // Note: You should probably use a proper password KDF
|
||||
//! # use crate::srp::client::SrpClient;
|
||||
//!
|
||||
//! let client = SrpClient::<Sha256>::new(&G_2048);
|
||||
//! ```
|
||||
//!
|
||||
//! Next send handshake data (username and `a_pub`) to the server and receive
|
||||
//! `salt` and `b_pub`:
|
||||
//!
|
||||
//! ```rust
|
||||
//! # let client = crate::srp::client::SrpClient::<sha2::Sha256>::new(&crate::srp::groups::G_2048);
|
||||
//! # fn server_response()-> (Vec<u8>, Vec<u8>) { (vec![], vec![]) }
|
||||
//!
|
||||
//! let mut a = [0u8; 64];
|
||||
//! // rng.fill_bytes(&mut a);
|
||||
//! let a_pub = client.compute_public_ephemeral(&a);
|
||||
//! let (salt, b_pub) = server_response();
|
||||
//! ```
|
||||
//!
|
||||
//! Process the server response and create verifier instance.
|
||||
//! process_reply can return error in case of malicious `b_pub`.
|
||||
//!
|
||||
//! ```rust
|
||||
//! # let client = crate::srp::client::SrpClient::<sha2::Sha256>::new(&crate::srp::groups::G_2048);
|
||||
//! # let a = [0u8; 64];
|
||||
//! # let username = b"username";
|
||||
//! # let password = b"password";
|
||||
//! # let salt = b"salt";
|
||||
//! # let b_pub = b"b_pub";
|
||||
//!
|
||||
//! let private_key = (username, password, salt);
|
||||
//! let verifier = client.process_reply(&a, username, password, salt, b_pub);
|
||||
//! ```
|
||||
//!
|
||||
//! Finally verify the server: first generate user proof,
|
||||
//! send it to the server and verify server proof in the reply. Note that
|
||||
//! `verify_server` method will return error in case of incorrect server reply.
|
||||
//!
|
||||
//! ```rust
|
||||
//! # let client = crate::srp::client::SrpClient::<sha2::Sha256>::new(&crate::srp::groups::G_2048);
|
||||
//! # let verifier = client.process_reply(b"", b"", b"", b"", b"1").unwrap();
|
||||
//! # fn send_proof(_: &[u8]) -> Vec<u8> { vec![173, 202, 13, 26, 207, 73, 0, 46, 121, 238, 48, 170, 96, 146, 60, 49, 88, 76, 12, 184, 152, 76, 207, 220, 140, 205, 190, 189, 117, 6, 131, 63] }
|
||||
//!
|
||||
//! let client_proof = verifier.proof();
|
||||
//! let server_proof = send_proof(client_proof);
|
||||
//! verifier.verify_server(&server_proof).unwrap();
|
||||
//! ```
|
||||
//!
|
||||
//! `key` contains shared secret key between user and the server. You can extract shared secret
|
||||
//! key using `key()` method.
|
||||
//! ```rust
|
||||
//! # let client = crate::srp::client::SrpClient::<sha2::Sha256>::new(&crate::srp::groups::G_2048);
|
||||
//! # let verifier = client.process_reply(b"", b"", b"", b"", b"1").unwrap();
|
||||
//!
|
||||
//! verifier.key();
|
||||
//!```
|
||||
//!
|
||||
//!
|
||||
//! For user registration on the server first generate salt (e.g. 32 bytes long)
|
||||
//! and get password verifier which depends on private key. Send username, salt
|
||||
//! and password verifier over protected channel to protect against
|
||||
//! Man-in-the-middle (MITM) attack for registration.
|
||||
//!
|
||||
//! ```rust
|
||||
//! # let client = crate::srp::client::SrpClient::<sha2::Sha256>::new(&crate::srp::groups::G_2048);
|
||||
//! # let username = b"username";
|
||||
//! # let password = b"password";
|
||||
//! # let salt = b"salt";
|
||||
//! # fn send_registration_data(_: &[u8], _: &[u8], _: &[u8]) {}
|
||||
//!
|
||||
//! let pwd_verifier = client.compute_verifier(username, password, salt);
|
||||
//! send_registration_data(username, salt, &pwd_verifier);
|
||||
//! ```
|
||||
|
||||
use digest::{Digest, Output};
|
||||
use num_bigint::BigUint;
|
||||
use std::marker::PhantomData;
|
||||
use subtle::ConstantTimeEq;
|
||||
|
||||
use crate::types::{SrpAuthError, SrpGroup};
|
||||
use crate::utils::{compute_k, compute_m1, compute_m2, compute_u};
|
||||
|
||||
/// SRP client state before handshake with the server.
|
||||
pub struct SrpClient<'a, D: Digest> {
|
||||
params: &'a SrpGroup,
|
||||
d: PhantomData<D>,
|
||||
}
|
||||
|
||||
/// SRP client state after handshake with the server.
|
||||
pub struct SrpClientVerifier<D: Digest> {
|
||||
m1: Output<D>,
|
||||
m2: Output<D>,
|
||||
key: Vec<u8>,
|
||||
}
|
||||
|
||||
impl<'a, D: Digest> SrpClient<'a, D> {
|
||||
/// Create new SRP client instance.
|
||||
pub fn new(params: &'a SrpGroup) -> Self {
|
||||
Self {
|
||||
params,
|
||||
d: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn compute_a_pub(&self, a: &BigUint) -> BigUint {
|
||||
self.params.g.modpow(a, &self.params.n)
|
||||
}
|
||||
|
||||
// H(<username> | ":" | <raw password>)
|
||||
pub fn compute_identity_hash(username: &[u8], password: &[u8]) -> Output<D> {
|
||||
let mut d = D::new();
|
||||
d.update(username);
|
||||
d.update(b":");
|
||||
d.update(password);
|
||||
d.finalize()
|
||||
}
|
||||
|
||||
// x = H(<salt> | H(<username> | ":" | <raw password>))
|
||||
pub fn compute_x(identity_hash: &[u8], salt: &[u8]) -> BigUint {
|
||||
let mut x = D::new();
|
||||
x.update(salt);
|
||||
x.update(identity_hash);
|
||||
BigUint::from_bytes_be(&x.finalize())
|
||||
}
|
||||
|
||||
// (B - (k * g^x)) ^ (a + (u * x)) % N
|
||||
pub fn compute_premaster_secret(
|
||||
&self,
|
||||
b_pub: &BigUint,
|
||||
k: &BigUint,
|
||||
x: &BigUint,
|
||||
a: &BigUint,
|
||||
u: &BigUint,
|
||||
) -> BigUint {
|
||||
// (k * g^x)
|
||||
let base = (k * (self.params.g.modpow(x, &self.params.n))) % &self.params.n;
|
||||
// Because we do operation in modulo N we can get: b_pub > base. That's not good. So we add N to b_pub to make sure.
|
||||
// B - kg^x
|
||||
let base = ((&self.params.n + b_pub) - &base) % &self.params.n;
|
||||
let exp = (u * x) + a;
|
||||
// S = (B - kg^x) ^ (a + ux)
|
||||
// or
|
||||
// S = base ^ exp
|
||||
base.modpow(&exp, &self.params.n)
|
||||
}
|
||||
|
||||
// v = g^x % N
|
||||
pub fn compute_v(&self, x: &BigUint) -> BigUint {
|
||||
self.params.g.modpow(x, &self.params.n)
|
||||
}
|
||||
|
||||
/// Get password verifier (v in RFC5054) for user registration on the server.
|
||||
pub fn compute_verifier(&self, username: &[u8], password: &[u8], salt: &[u8]) -> Vec<u8> {
|
||||
let identity_hash = Self::compute_identity_hash(username, password);
|
||||
let x = Self::compute_x(identity_hash.as_slice(), salt);
|
||||
self.compute_v(&x).to_bytes_be()
|
||||
}
|
||||
|
||||
/// Get public ephemeral value for handshaking with the server.
|
||||
/// g^a % N
|
||||
pub fn compute_public_ephemeral(&self, a: &[u8]) -> Vec<u8> {
|
||||
self.compute_a_pub(&BigUint::from_bytes_be(a)).to_bytes_be()
|
||||
}
|
||||
|
||||
/// Process server reply to the handshake.
|
||||
/// a is a random value,
|
||||
/// username, password is supplied by the user
|
||||
/// salt and b_pub come from the server
|
||||
pub fn process_reply(
|
||||
&self,
|
||||
a: &[u8],
|
||||
username: &[u8],
|
||||
password: &[u8],
|
||||
salt: &[u8],
|
||||
b_pub: &[u8],
|
||||
) -> Result<SrpClientVerifier<D>, SrpAuthError> {
|
||||
let a = BigUint::from_bytes_be(a);
|
||||
// let a_pub = BigUint::from_bytes_be(&a_pub_bytes);
|
||||
let a_pub = Self::compute_a_pub(&self, &a);
|
||||
|
||||
let b_pub = BigUint::from_bytes_be(b_pub);
|
||||
|
||||
// Safeguard against malicious B
|
||||
if &b_pub % &self.params.n == BigUint::default() {
|
||||
return Err(SrpAuthError::IllegalParameter("b_pub".to_owned()));
|
||||
}
|
||||
|
||||
let u = compute_u::<D>(&a_pub.to_bytes_be(), &b_pub.to_bytes_be());
|
||||
let k = compute_k::<D>(self.params);
|
||||
let identity_hash = Self::compute_identity_hash(&[], password);
|
||||
let x = Self::compute_x(identity_hash.as_slice(), salt);
|
||||
|
||||
let key = self.compute_premaster_secret(&b_pub, &k, &x, &a, &u);
|
||||
let key = D::digest(key.to_bytes_be());
|
||||
|
||||
let m1 = compute_m1::<D>(
|
||||
&a_pub.to_bytes_be(),
|
||||
&b_pub.to_bytes_be(),
|
||||
&key,
|
||||
username,
|
||||
salt,
|
||||
self.params,
|
||||
);
|
||||
|
||||
let m2 = compute_m2::<D>(&a_pub.to_bytes_be(), &m1, &key);
|
||||
|
||||
Ok(SrpClientVerifier {
|
||||
m1,
|
||||
m2,
|
||||
key: key.to_vec(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Digest> SrpClientVerifier<D> {
|
||||
/// Get shared secret key without authenticating server, e.g. for using with
|
||||
/// authenticated encryption modes. DO NOT USE this method without
|
||||
/// some kind of secure authentication
|
||||
pub fn key(&self) -> &[u8] {
|
||||
&self.key
|
||||
}
|
||||
|
||||
/// Verification data for sending to the server.
|
||||
pub fn proof(&self) -> &[u8] {
|
||||
self.m1.as_slice()
|
||||
}
|
||||
|
||||
/// Verify server reply to verification data.
|
||||
pub fn verify_server(&self, reply: &[u8]) -> Result<(), SrpAuthError> {
|
||||
if self.m2.ct_eq(reply).unwrap_u8() != 1 {
|
||||
// aka == 0
|
||||
Err(SrpAuthError::BadRecordMac("server".to_owned()))
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
57
apple-private-apis/icloud-auth/rustcrypto-srp/src/groups.rs
Normal file
57
apple-private-apis/icloud-auth/rustcrypto-srp/src/groups.rs
Normal file
@@ -0,0 +1,57 @@
|
||||
//! Groups from [RFC 5054](https://tools.ietf.org/html/rfc5054)
|
||||
//!
|
||||
//! It is strongly recommended to use them instead of custom generated
|
||||
//! groups. Additionally it is not recommended to use `G_1024` and `G_1536`,
|
||||
//! they are provided only for compatibility with the legacy software.
|
||||
use crate::types::SrpGroup;
|
||||
use lazy_static::lazy_static;
|
||||
use num_bigint::BigUint;
|
||||
|
||||
lazy_static! {
|
||||
pub static ref G_1024: SrpGroup = SrpGroup {
|
||||
n: BigUint::from_bytes_be(include_bytes!("groups/1024.bin")),
|
||||
g: BigUint::from_bytes_be(&[2]),
|
||||
};
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
pub static ref G_1536: SrpGroup = SrpGroup {
|
||||
n: BigUint::from_bytes_be(include_bytes!("groups/1536.bin")),
|
||||
g: BigUint::from_bytes_be(&[2]),
|
||||
};
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
pub static ref G_2048: SrpGroup = SrpGroup {
|
||||
n: BigUint::from_bytes_be(include_bytes!("groups/2048.bin")),
|
||||
g: BigUint::from_bytes_be(&[2]),
|
||||
};
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
pub static ref G_3072: SrpGroup = SrpGroup {
|
||||
n: BigUint::from_bytes_be(include_bytes!("groups/3072.bin")),
|
||||
g: BigUint::from_bytes_be(&[5]),
|
||||
};
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
pub static ref G_4096: SrpGroup = SrpGroup {
|
||||
n: BigUint::from_bytes_be(include_bytes!("groups/4096.bin")),
|
||||
g: BigUint::from_bytes_be(&[5]),
|
||||
};
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
pub static ref G_6144: SrpGroup = SrpGroup {
|
||||
n: BigUint::from_bytes_be(include_bytes!("groups/6144.bin")),
|
||||
g: BigUint::from_bytes_be(&[5]),
|
||||
};
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
pub static ref G_8192: SrpGroup = SrpGroup {
|
||||
n: BigUint::from_bytes_be(include_bytes!("groups/8192.bin")),
|
||||
g: BigUint::from_bytes_be(&[19]),
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
î¯
|
||||
¹³<EFBFBD>Öœ3ø
|
||||
ú<EFBFBD>Åè`ra‡uÿ<ž¢1Lœ%evÖtßt–ê<E28093>Ó8;HÖ’ÆààÕØâP¹‹äŽI\`‰ÚÑ]Ç×´aTÖ¶ÎŽôi±]I‚U›){Ï…Å)õffWìhí¼<rlÀ/ÔËô—nªšýQ8þƒvC[ŸÆ/Àëã
|
||||
@@ -0,0 +1 @@
|
||||
ťď<Żą9'z±ń*†¤{»ŰĄô™¬L€ľî©aKĚM_O_Un'ËŢQĆ©Kä`z)X<>; ĐřC€¶U»š"čÜߊ|ěgđĐ<C491>4±Čąy‰›`žăş¶=GT<47><54>ŰűüvN?KSÝťˇ‹ý>+śŚőnß•94–'Ű/Ő=$·Ä†ew.C}lŚäBsJ÷Ě·®<C2B7>|&J㩾¸Š/鸵).Z˙^‘GžŚç˘Ś$BĆó“Iš#MĎvăţŃ5ů»
|
||||
@@ -0,0 +1,2 @@
|
||||
¬kÛA2Jš›ñfÞ^‰X/¯r¶e‡îü1’”=µ`P£s)Ë´ ™í<E284A2>“àuwg¡=Õ#«K1
|
||||
ÍH©ÚýPè9ií·g°Ï`•š:³fûÕúªè)©–/“¸Uùy“ì—^ê¨
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
57
apple-private-apis/icloud-auth/rustcrypto-srp/src/lib.rs
Normal file
57
apple-private-apis/icloud-auth/rustcrypto-srp/src/lib.rs
Normal file
@@ -0,0 +1,57 @@
|
||||
#![allow(clippy::many_single_char_names)]
|
||||
#![doc(html_logo_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo_small.png")]
|
||||
#![doc = include_str!("../README.md")]
|
||||
|
||||
//! # Usage
|
||||
//! Add `srp` dependency to your `Cargo.toml`:
|
||||
//!
|
||||
//! ```toml
|
||||
//! [dependencies]
|
||||
//! srp = "0.6"
|
||||
//! ```
|
||||
//!
|
||||
//! Next read documentation for [`client`](client/index.html) and
|
||||
//! [`server`](server/index.html) modules.
|
||||
//!
|
||||
//! # Algorithm description
|
||||
//! Here we briefly describe implemented algorithm. For additional information
|
||||
//! refer to SRP literature. All arithmetic is done modulo `N`, where `N` is a
|
||||
//! large safe prime (`N = 2q+1`, where `q` is prime). Additionally `g` MUST be
|
||||
//! a generator modulo `N`. It's STRONGLY recommended to use SRP parameters
|
||||
//! provided by this crate in the [`groups`](groups/index.html) module.
|
||||
//!
|
||||
//! | Client | Data transfer | Server |
|
||||
//! |------------------------|-------------------|---------------------------------|
|
||||
//! |`a_pub = g^a` | — `a_pub`, `I` —> | (lookup `s`, `v` for given `I`) |
|
||||
//! |`x = PH(P, s)` | <— `b_pub`, `s` — | `b_pub = k*v + g^b` |
|
||||
//! |`u = H(a_pub ‖ b_pub)` | | `u = H(a_pub ‖ b_pub)` |
|
||||
//! |`s = (b_pub - k*g^x)^(a+u*x)` | | `S = (b_pub - k*g^x)^(a+u*x)` |
|
||||
//! |`K = H(s)` | | `K = H(s)` |
|
||||
//! |`M1 = H(A ‖ B ‖ K)` | — `M1` —> | (verify `M1`) |
|
||||
//! |(verify `M2`) | <— `M2` — | `M2 = H(A ‖ M1 ‖ K)` |
|
||||
//!
|
||||
//! Variables and notations have the following meaning:
|
||||
//!
|
||||
//! - `I` — user identity (username)
|
||||
//! - `P` — user password
|
||||
//! - `H` — one-way hash function
|
||||
//! - `PH` — password hashing algroithm, in the RFC 5054 described as
|
||||
//! `H(s ‖ H(I ‖ ":" ‖ P))`
|
||||
//! - `^` — (modular) exponentiation
|
||||
//! - `‖` — concatenation
|
||||
//! - `x` — user private key
|
||||
//! - `s` — salt generated by user and stored on the server
|
||||
//! - `v` — password verifier equal to `g^x` and stored on the server
|
||||
//! - `a`, `b` — secret ephemeral values (at least 256 bits in length)
|
||||
//! - `A`, `B` — Public ephemeral values
|
||||
//! - `u` — scrambling parameter
|
||||
//! - `k` — multiplier parameter (`k = H(N || g)` in SRP-6a)
|
||||
//!
|
||||
//! [1]: https://en.wikipedia.org/wiki/Secure_Remote_Password_protocol
|
||||
//! [2]: https://tools.ietf.org/html/rfc5054
|
||||
|
||||
pub mod client;
|
||||
pub mod groups;
|
||||
pub mod server;
|
||||
pub mod types;
|
||||
pub mod utils;
|
||||
190
apple-private-apis/icloud-auth/rustcrypto-srp/src/server.rs
Normal file
190
apple-private-apis/icloud-auth/rustcrypto-srp/src/server.rs
Normal file
@@ -0,0 +1,190 @@
|
||||
//! SRP server implementation
|
||||
//!
|
||||
//! # Usage
|
||||
//! First receive user's username and public value `a_pub`, retrieve from a
|
||||
//! database the salt and verifier for a given username. Generate `b` and public value `b_pub`.
|
||||
//!
|
||||
//!
|
||||
//! ```rust
|
||||
//! use crate::srp::groups::G_2048;
|
||||
//! use sha2::Sha256; // Note: You should probably use a proper password KDF
|
||||
//! # use crate::srp::server::SrpServer;
|
||||
//! # fn get_client_request()-> (Vec<u8>, Vec<u8>) { (vec![], vec![])}
|
||||
//! # fn get_user(_: &[u8])-> (Vec<u8>, Vec<u8>) { (vec![], vec![])}
|
||||
//!
|
||||
//! let server = SrpServer::<Sha256>::new(&G_2048);
|
||||
//! let (username, a_pub) = get_client_request();
|
||||
//! let (salt, v) = get_user(&username);
|
||||
//! let mut b = [0u8; 64];
|
||||
//! // rng.fill_bytes(&mut b);
|
||||
//! let b_pub = server.compute_public_ephemeral(&b, &v);
|
||||
//! ```
|
||||
//!
|
||||
//! Next send to user `b_pub` and `salt` from user record
|
||||
//!
|
||||
//! Next process the user response:
|
||||
//!
|
||||
//! ```rust
|
||||
//! # let server = crate::srp::server::SrpServer::<sha2::Sha256>::new(&crate::srp::groups::G_2048);
|
||||
//! # fn get_client_response() -> Vec<u8> { vec![1] }
|
||||
//! # let b = [0u8; 64];
|
||||
//! # let v = b"";
|
||||
//!
|
||||
//! let a_pub = get_client_response();
|
||||
//! let verifier = server.process_reply(&b, v, &a_pub).unwrap();
|
||||
//! ```
|
||||
//!
|
||||
//!
|
||||
//! And finally receive user proof, verify it and send server proof in the
|
||||
//! reply:
|
||||
//!
|
||||
//! ```rust
|
||||
//! # let server = crate::srp::server::SrpServer::<sha2::Sha256>::new(&crate::srp::groups::G_2048);
|
||||
//! # let verifier = server.process_reply(b"", b"", b"1").unwrap();
|
||||
//! # fn get_client_proof()-> Vec<u8> { vec![26, 80, 8, 243, 111, 162, 238, 171, 208, 237, 207, 46, 46, 137, 44, 213, 105, 208, 84, 224, 244, 216, 103, 145, 14, 103, 182, 56, 242, 4, 179, 57] };
|
||||
//! # fn send_proof(_: &[u8]) { };
|
||||
//!
|
||||
//! let client_proof = get_client_proof();
|
||||
//! verifier.verify_client(&client_proof).unwrap();
|
||||
//! send_proof(verifier.proof());
|
||||
//! ```
|
||||
//!
|
||||
//!
|
||||
//! `key` contains shared secret key between user and the server. You can extract shared secret
|
||||
//! key using `key()` method.
|
||||
//! ```rust
|
||||
//! # let server = crate::srp::server::SrpServer::<sha2::Sha256>::new(&crate::srp::groups::G_2048);
|
||||
//! # let verifier = server.process_reply(b"", b"", b"1").unwrap();
|
||||
//!
|
||||
//! verifier.key();
|
||||
//!```
|
||||
//!
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use digest::{Digest, Output};
|
||||
use num_bigint::BigUint;
|
||||
use subtle::ConstantTimeEq;
|
||||
|
||||
use crate::types::{SrpAuthError, SrpGroup};
|
||||
use crate::utils::{compute_k, compute_m1, compute_m2, compute_u};
|
||||
|
||||
/// SRP server state
|
||||
pub struct SrpServer<'a, D: Digest> {
|
||||
params: &'a SrpGroup,
|
||||
d: PhantomData<D>,
|
||||
}
|
||||
|
||||
/// SRP server state after handshake with the client.
|
||||
pub struct SrpServerVerifier<D: Digest> {
|
||||
m1: Output<D>,
|
||||
m2: Output<D>,
|
||||
key: Vec<u8>,
|
||||
}
|
||||
|
||||
impl<'a, D: Digest> SrpServer<'a, D> {
|
||||
/// Create new server state.
|
||||
pub fn new(params: &'a SrpGroup) -> Self {
|
||||
Self {
|
||||
params,
|
||||
d: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
// k*v + g^b % N
|
||||
pub fn compute_b_pub(&self, b: &BigUint, k: &BigUint, v: &BigUint) -> BigUint {
|
||||
let inter = (k * v) % &self.params.n;
|
||||
(inter + self.params.g.modpow(b, &self.params.n)) % &self.params.n
|
||||
}
|
||||
|
||||
// <premaster secret> = (A * v^u) ^ b % N
|
||||
pub fn compute_premaster_secret(
|
||||
&self,
|
||||
a_pub: &BigUint,
|
||||
v: &BigUint,
|
||||
u: &BigUint,
|
||||
b: &BigUint,
|
||||
) -> BigUint {
|
||||
// (A * v^u)
|
||||
let base = (a_pub * v.modpow(u, &self.params.n)) % &self.params.n;
|
||||
base.modpow(b, &self.params.n)
|
||||
}
|
||||
|
||||
/// Get public ephemeral value for sending to the client.
|
||||
pub fn compute_public_ephemeral(&self, b: &[u8], v: &[u8]) -> Vec<u8> {
|
||||
self.compute_b_pub(
|
||||
&BigUint::from_bytes_be(b),
|
||||
&compute_k::<D>(self.params),
|
||||
&BigUint::from_bytes_be(v),
|
||||
)
|
||||
.to_bytes_be()
|
||||
}
|
||||
|
||||
/// Process client reply to the handshake.
|
||||
/// b is a random value,
|
||||
/// v is the provided during initial user registration
|
||||
pub fn process_reply(
|
||||
&self,
|
||||
b: &[u8],
|
||||
v: &[u8],
|
||||
a_pub: &[u8],
|
||||
username: &[u8],
|
||||
salt: &[u8],
|
||||
) -> Result<SrpServerVerifier<D>, SrpAuthError> {
|
||||
let b = BigUint::from_bytes_be(b);
|
||||
let v = BigUint::from_bytes_be(v);
|
||||
let a_pub = BigUint::from_bytes_be(a_pub);
|
||||
|
||||
let k = compute_k::<D>(self.params);
|
||||
let b_pub = self.compute_b_pub(&b, &k, &v);
|
||||
|
||||
// Safeguard against malicious A
|
||||
if &a_pub % &self.params.n == BigUint::default() {
|
||||
return Err(SrpAuthError::IllegalParameter("a_pub".to_owned()));
|
||||
}
|
||||
|
||||
let u = compute_u::<D>(&a_pub.to_bytes_be(), &b_pub.to_bytes_be());
|
||||
|
||||
let key = self.compute_premaster_secret(&a_pub, &v, &u, &b);
|
||||
|
||||
let m1 = compute_m1::<D>(
|
||||
&a_pub.to_bytes_be(),
|
||||
&b_pub.to_bytes_be(),
|
||||
&key.to_bytes_be(),
|
||||
username,
|
||||
salt,
|
||||
self.params,
|
||||
);
|
||||
|
||||
let m2 = compute_m2::<D>(&a_pub.to_bytes_be(), &m1, &key.to_bytes_be());
|
||||
|
||||
Ok(SrpServerVerifier {
|
||||
m1,
|
||||
m2,
|
||||
key: key.to_bytes_be(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Digest> SrpServerVerifier<D> {
|
||||
/// Get shared secret between user and the server. (do not forget to verify
|
||||
/// that keys are the same!)
|
||||
pub fn key(&self) -> &[u8] {
|
||||
&self.key
|
||||
}
|
||||
|
||||
/// Verification data for sending to the client.
|
||||
pub fn proof(&self) -> &[u8] {
|
||||
// TODO not Output
|
||||
self.m2.as_slice()
|
||||
}
|
||||
|
||||
/// Process user proof of having the same shared secret.
|
||||
pub fn verify_client(&self, reply: &[u8]) -> Result<(), SrpAuthError> {
|
||||
if self.m1.ct_eq(reply).unwrap_u8() != 1 {
|
||||
// aka == 0
|
||||
Err(SrpAuthError::BadRecordMac("client".to_owned()))
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
45
apple-private-apis/icloud-auth/rustcrypto-srp/src/types.rs
Normal file
45
apple-private-apis/icloud-auth/rustcrypto-srp/src/types.rs
Normal file
@@ -0,0 +1,45 @@
|
||||
//! Additional SRP types.
|
||||
use num_bigint::BigUint;
|
||||
use std::fmt;
|
||||
|
||||
/// SRP authentication error.
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
pub enum SrpAuthError {
|
||||
IllegalParameter(String),
|
||||
BadRecordMac(String),
|
||||
}
|
||||
|
||||
impl fmt::Display for SrpAuthError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
SrpAuthError::IllegalParameter(param) => {
|
||||
write!(f, "illegal_parameter: bad '{}' value", param)
|
||||
}
|
||||
SrpAuthError::BadRecordMac(param) => {
|
||||
write!(f, "bad_record_mac: incorrect '{}' proof", param)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Group used for SRP computations
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
pub struct SrpGroup {
|
||||
/// A large safe prime (N = 2q+1, where q is prime)
|
||||
pub n: BigUint,
|
||||
/// A generator modulo N
|
||||
pub g: BigUint,
|
||||
}
|
||||
|
||||
// #[cfg(test)]
|
||||
// mod tests {
|
||||
// use crate::groups::G_1024;
|
||||
// use crate::utils::compute_k;
|
||||
// use sha1::Sha1;
|
||||
|
||||
// #[test]
|
||||
// fn test_k_1024_sha1() {
|
||||
// let k = compute_k::<Sha1>(&G_1024).to_bytes_be();
|
||||
// assert_eq!(&k, include_bytes!("test/k_sha1_1024.bin"));
|
||||
// }
|
||||
// }
|
||||
70
apple-private-apis/icloud-auth/rustcrypto-srp/src/utils.rs
Normal file
70
apple-private-apis/icloud-auth/rustcrypto-srp/src/utils.rs
Normal file
@@ -0,0 +1,70 @@
|
||||
use digest::{Digest, Output};
|
||||
use num_bigint::BigUint;
|
||||
|
||||
use crate::types::SrpGroup;
|
||||
|
||||
// u = H(PAD(A) | PAD(B))
|
||||
pub fn compute_u<D: Digest>(a_pub: &[u8], b_pub: &[u8]) -> BigUint {
|
||||
let mut u = D::new();
|
||||
u.update(a_pub);
|
||||
u.update(b_pub);
|
||||
BigUint::from_bytes_be(&u.finalize())
|
||||
}
|
||||
|
||||
// k = H(N | PAD(g))
|
||||
pub fn compute_k<D: Digest>(params: &SrpGroup) -> BigUint {
|
||||
let n = params.n.to_bytes_be();
|
||||
let g_bytes = params.g.to_bytes_be();
|
||||
let mut buf = vec![0u8; n.len()];
|
||||
let l = n.len() - g_bytes.len();
|
||||
buf[l..].copy_from_slice(&g_bytes);
|
||||
|
||||
let mut d = D::new();
|
||||
d.update(&n);
|
||||
d.update(&buf);
|
||||
BigUint::from_bytes_be(d.finalize().as_slice())
|
||||
}
|
||||
|
||||
// M1 = H(A, B, K) this doesn't follow the spec but apparently no one does for M1
|
||||
// M1 should equal = H(H(N) XOR H(g) | H(U) | s | A | B | K) according to the spec
|
||||
pub fn compute_m1<D: Digest>(
|
||||
a_pub: &[u8],
|
||||
b_pub: &[u8],
|
||||
key: &[u8],
|
||||
username: &[u8],
|
||||
salt: &[u8],
|
||||
params: &SrpGroup,
|
||||
) -> Output<D> {
|
||||
let n = params.n.to_bytes_be();
|
||||
let g_bytes = params.g.to_bytes_be();
|
||||
//pad g and n to the same length
|
||||
let mut g = vec![0; n.len() - g_bytes.len()];
|
||||
g.extend_from_slice(&g_bytes);
|
||||
|
||||
// Compute the hash of n and g
|
||||
let mut g_hash = D::digest(&g);
|
||||
let n_hash = D::digest(&n);
|
||||
|
||||
// XOR the hashes
|
||||
for i in 0..g_hash.len() {
|
||||
g_hash[i] ^= n_hash[i];
|
||||
}
|
||||
|
||||
let mut d = D::new();
|
||||
d.update(&g_hash);
|
||||
d.update(D::digest(username));
|
||||
d.update(salt);
|
||||
d.update(a_pub);
|
||||
d.update(b_pub);
|
||||
d.update(key);
|
||||
d.finalize()
|
||||
}
|
||||
|
||||
// M2 = H(A, M1, K)
|
||||
pub fn compute_m2<D: Digest>(a_pub: &[u8], m1: &Output<D>, key: &[u8]) -> Output<D> {
|
||||
let mut d = D::new();
|
||||
d.update(&a_pub);
|
||||
d.update(&m1);
|
||||
d.update(&key);
|
||||
d.finalize()
|
||||
}
|
||||
Reference in New Issue
Block a user