-
Notifications
You must be signed in to change notification settings - Fork 161
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
extras: Add APIs for RSA Blind Signatures #232
Changes from all commits
090eab8
e0bc477
b9f9d7f
e5b4dd0
cb7a828
d6c6dd5
d2a28e5
56d0253
60f26f0
d239017
7c37d7a
ec9e122
925d7b9
606f74d
a8d0338
bd1e490
b9403e5
eec135e
616b027
ec0d4da
7500681
8bf79bd
ae89be1
c4f4a15
bda85da
97094e7
cc94704
e760d48
bb6c618
0ab2368
7a317cd
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -98,6 +98,14 @@ extension ArbitraryPrecisionInteger { | |
public init<Bytes: ContiguousBytes>(bytes: Bytes) throws { | ||
self._backing = try BackingStorage(bytes: bytes) | ||
} | ||
|
||
/// Create an `ArbitraryPrecisionInteger` from a hex string. | ||
/// | ||
/// - Parameter hexString: Hex byte string (big-endian, no `0x` prefix, may start with `-` for a negative number). | ||
@inlinable | ||
public init(hexString: String) throws { | ||
self._backing = try BackingStorage(hexString: hexString) | ||
} | ||
} | ||
|
||
extension ArbitraryPrecisionInteger.BackingStorage { | ||
|
@@ -112,8 +120,27 @@ extension ArbitraryPrecisionInteger.BackingStorage { | |
throw CryptoBoringWrapperError.internalBoringSSLError() | ||
} | ||
} | ||
|
||
@inlinable | ||
convenience init(hexString: String) throws { | ||
self.init() | ||
try hexString.withCString { hexStringPtr in | ||
/// `BN_hex2bin` takes a `BIGNUM **` so we need a double WUMP dance. | ||
try withUnsafeMutablePointer(to: &self._backing) { backingPtr in | ||
var backingPtr: UnsafeMutablePointer<BIGNUM>? = backingPtr | ||
try withUnsafeMutablePointer(to: &backingPtr) { backingPtrPtr in | ||
/// `BN_hex2bin` returns the number of bytes of `in` processed or zero on error. | ||
guard CCryptoBoringSSL_BN_hex2bn(backingPtrPtr, hexStringPtr) == hexString.count else { | ||
throw CryptoBoringWrapperError.incorrectParameterSize | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} | ||
|
||
|
||
|
||
// MARK: - Pointer helpers | ||
|
||
extension ArbitraryPrecisionInteger { | ||
|
@@ -381,6 +408,49 @@ extension ArbitraryPrecisionInteger: SignedNumeric { | |
} | ||
} | ||
|
||
// MARK: - Other arithmetic operations | ||
|
||
extension ArbitraryPrecisionInteger { | ||
@inlinable | ||
public static func gcd(_ a: ArbitraryPrecisionInteger, _ b: ArbitraryPrecisionInteger) throws -> ArbitraryPrecisionInteger { | ||
var result = ArbitraryPrecisionInteger() | ||
|
||
guard result.withUnsafeMutableBignumPointer({ resultPtr in | ||
a.withUnsafeBignumPointer { aPtr in | ||
b.withUnsafeBignumPointer { bPtr in | ||
ArbitraryPrecisionInteger.withUnsafeBN_CTX { bnCtx in | ||
CCryptoBoringSSL_BN_gcd(resultPtr, aPtr, bPtr, bnCtx) | ||
} | ||
} | ||
} | ||
}) == 1 else { | ||
throw CryptoBoringWrapperError.internalBoringSSLError() | ||
} | ||
|
||
return result | ||
} | ||
|
||
@inlinable | ||
public func isCoprime(with other: ArbitraryPrecisionInteger) throws -> Bool { | ||
try Self.gcd(self, other) == 1 | ||
} | ||
|
||
@inlinable | ||
public static func random(inclusiveMin: UInt64, exclusiveMax: ArbitraryPrecisionInteger) throws -> ArbitraryPrecisionInteger { | ||
var result = ArbitraryPrecisionInteger() | ||
|
||
guard result.withUnsafeMutableBignumPointer({ resultPtr in | ||
exclusiveMax.withUnsafeBignumPointer { exclusiveMaxPtr in | ||
CCryptoBoringSSL_BN_rand_range_ex(resultPtr, inclusiveMin, exclusiveMaxPtr) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This doesn't compile on Android armv7, a 32-bit platform, with the following error from my Android CI:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @finagolfin sorry about that oversight. I'm sure the fix should be pretty minimal but unfortunately I don't have a way of validating it and it's not part of our CI. Presumably the fix here is to take a Are you able to test this and open a PR? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Actually, I can reproduce this locally when building for watchOS simulator. Let me put up a patch. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
} | ||
}) == 1 else { | ||
throw CryptoBoringWrapperError.internalBoringSSLError() | ||
} | ||
|
||
return result | ||
} | ||
} | ||
|
||
// MARK: - Serializing | ||
|
||
extension Data { | ||
|
@@ -408,6 +478,12 @@ extension Data { | |
|
||
assert(written == byteCount) | ||
} | ||
|
||
@inlinable | ||
public init(bytesOf integer: ArbitraryPrecisionInteger, paddedToSize paddingSize: Int) throws { | ||
self.init(capacity: paddingSize) | ||
try self.append(bytesOf: integer, paddedToSize: paddingSize) | ||
} | ||
} | ||
|
||
// MARK: - Printing | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typically we'd spell this with a range, rather than the explicit bounds.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This one is an interesting one! I initially reached for a
Range
but a range needs to have a homogeneous type and the underlying call we're wrapping does not take twoBIGNUM*
, but instead oneBN_ULONG
and oneBIGNUM*
.This left me with two options:
Range<ArbitraryPrecisionInteger>
and fail if the lower bound is too large.When possible I thought we should be providing API that prohibits invalid use if we can leverage the type system to do so.