apple / swift-crypto

Open-source implementation of a substantial portion of the API of Apple CryptoKit suitable for use on Linux platforms.
https://apple.github.io/swift-crypto
Apache License 2.0
1.43k stars 151 forks source link

extras: Add APIs for RSA Blind Signatures #232

Closed simonjbeaumont closed 1 week ago

simonjbeaumont commented 1 month ago

Motivation

RFC 9474 defines the RSA Blind Signatures protocol^0, which are a useful building block of privacy-preserving schemes.

Modifications

This PR adds the following public API surface to implement the RSA Blind Signatures protocol:

public struct _RSA.BlindSigning.Parameters<H: HashFunction> {}

extension _RSA.BlindSigning.Parameters where H == SHA384 {
    public static let RSABSSA_SHA384_PSS_Randomized: Self<SHA384>
    public static let RSABSSA_SHA384_PSS_Deterministic: Self<SHA384>
    public static let RSABSSA_SHA384_PSSZERO_Randomized: Self<SHA384>
    public static let RSABSSA_SHA384_PSSZERO_Deterministic: Self<SHA384>
}

public struct _RSA.BlindSigning.PrivateKey {
    public typealias Parameters = _RSA.BlindSigning.Parameters<H>

    // ... similar initializers as other protocol-segreated key types, but taking parameters parameter ...

    // ... same properties as other protocol-segregated key types ...

    public func blindSignature<D: DataProtocol>(for message: D) throws -> _RSA.BlindSigning.BlindSignature
}

public struct _RSA.BlindSigning.PublicKey {
    public typealias Parameters = _RSA.BlindSigning.Parameters<H>

    // ... similar initializers as other protocol-segreated key types, but taking parameters parameter ...

    // ... same properties as other protocol-segregated key types ...

    public func prepare<D: DataProtocol>(_ message: D) -> _RSA.BlindSigning.PreparedMessage

    public func blind(_ message: _RSA.BlindSigning.PreparedMessage) throws -> (blindedMessage: Data, blindInverse: _RSA.BlindSigning.BlindInverse)

    public func finalize(_ signature: _RSA.BlindSigning.BlindSignature, for message: _RSA.BlindSigning.PreparedMessage,
 blindInverse: _RSA.BlindSigning.BlindInverse) throws -> _RSA.Signing.RSASignature

    public func isValidSignature(_ signature: _RSA.Signing.RSASignature, for message: _RSA.BlindSigning.PreparedMessage) -> Bool
}

It also adds tests using the test vectors from the RFC, where possible. That is, for each of the operations except for blind, which we don't have the BoringSSL APIs that would allow us to inject the fixed salt value from the test vectors.

While it's possible to implement the server-side operations using Security framework, it does not expose the APIs we would need to implement the client-side operations so, because the goal is to also provide the client-side operations in a subsequent PR, the implementation uses BoringSSL on all platforms.

In order to construct the RSA keys from the test vector parameters, some BoringSSL helpers were added.

Result

New API in the _CryptoExtras module for the the RSA Blind Signatures protocol as defined in RFC 9474, with support for all named variants: for the RSABSSA_SHA384_PSS_Randomized, RSABSSA_SHA384_PSS_Deterministic, RSABSSA_SHA384_PSSZERO_Randomized, and RSABSSA_SHA384_PSSZERO_Deterministic.

simonjbeaumont commented 1 month ago

@Lukasa this is ready for another pass when you have time.

simonjbeaumont commented 3 weeks ago

@Lukasa OK, thanks for the latest round of feedback. I've addressed all that now, so it's ready for another pass.

simonjbeaumont commented 1 week ago

@Lukasa as we discussed, now that we have ArbitraryPrecisionInteger and FiniteFieldArithmeticContext moved to CryptoBoringWrapper, I've replaced the use of manually managed BIGNUM in the implementation with the memory managed types. Hopefully this makes it much easier to be confident in the correctness.

simonjbeaumont commented 1 week ago

@swift-server-bot test this please