-
Notifications
You must be signed in to change notification settings - Fork 166
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Support loading RSAPSS public keys with parameters (#268)
* Support loading RSAPSS public keys with parameters Parameters are stripped and the key is treated as a regular public key. * address review + reset algorithm as well * run update_cmakelists.sh * attempt to fix the cmake build * include FetchContent * early return for non-PSS keys * simplify code
- Loading branch information
1 parent
ffca28b
commit b639b5b
Showing
6 changed files
with
206 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// This source file is part of the SwiftCrypto open source project | ||
// | ||
// Copyright (c) 2024 Apple Inc. and the SwiftCrypto project authors | ||
// Licensed under Apache License v2.0 | ||
// | ||
// See LICENSE.txt for license information | ||
// See CONTRIBUTORS.md for the list of SwiftCrypto project authors | ||
// | ||
// SPDX-License-Identifier: Apache-2.0 | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
import SwiftASN1 | ||
|
||
struct SubjectPublicKeyInfo: DERImplicitlyTaggable, Hashable { | ||
static var defaultIdentifier: ASN1Identifier { | ||
.sequence | ||
} | ||
|
||
var algorithmIdentifier: RFC5480AlgorithmIdentifier | ||
|
||
var key: ASN1BitString | ||
|
||
init(derEncoded rootNode: ASN1Node, withIdentifier identifier: ASN1Identifier) throws { | ||
// The SPKI block looks like this: | ||
// | ||
// SubjectPublicKeyInfo ::= SEQUENCE { | ||
// algorithm AlgorithmIdentifier, | ||
// subjectPublicKey BIT STRING | ||
// } | ||
self = try DER.sequence(rootNode, identifier: identifier) { nodes in | ||
let algorithmIdentifier = try RFC5480AlgorithmIdentifier(derEncoded: &nodes) | ||
let key = try ASN1BitString(derEncoded: &nodes) | ||
|
||
return SubjectPublicKeyInfo(algorithmIdentifier: algorithmIdentifier, key: key) | ||
} | ||
} | ||
|
||
private init(algorithmIdentifier: RFC5480AlgorithmIdentifier, key: ASN1BitString) { | ||
self.algorithmIdentifier = algorithmIdentifier | ||
self.key = key | ||
} | ||
|
||
internal init(algorithmIdentifier: RFC5480AlgorithmIdentifier, key: [UInt8]) { | ||
self.algorithmIdentifier = algorithmIdentifier | ||
self.key = ASN1BitString(bytes: key[...]) | ||
} | ||
|
||
func serialize(into coder: inout DER.Serializer, withIdentifier identifier: ASN1Identifier) throws { | ||
try coder.appendConstructedNode(identifier: identifier) { coder in | ||
try coder.serialize(self.algorithmIdentifier) | ||
try coder.serialize(self.key) | ||
} | ||
} | ||
} | ||
|
||
struct RFC5480AlgorithmIdentifier: DERImplicitlyTaggable, Hashable { | ||
static var defaultIdentifier: ASN1Identifier { | ||
.sequence | ||
} | ||
|
||
var algorithm: ASN1ObjectIdentifier | ||
|
||
var parameters: ASN1Any? | ||
|
||
init(algorithm: ASN1ObjectIdentifier, parameters: ASN1Any?) { | ||
self.algorithm = algorithm | ||
self.parameters = parameters | ||
} | ||
|
||
init(derEncoded rootNode: ASN1Node, withIdentifier identifier: ASN1Identifier) throws { | ||
// The AlgorithmIdentifier block looks like this. | ||
// | ||
// AlgorithmIdentifier ::= SEQUENCE { | ||
// algorithm OBJECT IDENTIFIER, | ||
// parameters ANY DEFINED BY algorithm OPTIONAL | ||
// } | ||
// | ||
// ECParameters ::= CHOICE { | ||
// namedCurve OBJECT IDENTIFIER | ||
// -- implicitCurve NULL | ||
// -- specifiedCurve SpecifiedECDomain | ||
// } | ||
// | ||
// We don't bother with helpers: we just try to decode it directly. | ||
self = try DER.sequence(rootNode, identifier: identifier) { nodes in | ||
let algorithmOID = try ASN1ObjectIdentifier(derEncoded: &nodes) | ||
|
||
let parameters = nodes.next().map { ASN1Any(derEncoded: $0) } | ||
|
||
return .init(algorithm: algorithmOID, parameters: parameters) | ||
} | ||
} | ||
|
||
func serialize(into coder: inout DER.Serializer, withIdentifier identifier: ASN1Identifier) throws { | ||
try coder.appendConstructedNode(identifier: identifier) { coder in | ||
try coder.serialize(self.algorithm) | ||
if let parameters = self.parameters { | ||
try coder.serialize(parameters) | ||
} | ||
} | ||
} | ||
} | ||
|
||
extension SubjectPublicKeyInfo { | ||
static func stripRsaPssParameters(derEncoded: [UInt8]) throws -> [UInt8] { | ||
guard var spki = try? SubjectPublicKeyInfo(derEncoded: derEncoded), | ||
spki.algorithmIdentifier.algorithm == .AlgorithmIdentifier.rsaPSS | ||
else { | ||
// If it's neither a SPKI nor a PSS key, we don't have to modify it. | ||
return derEncoded | ||
} | ||
|
||
spki.algorithmIdentifier.algorithm = .AlgorithmIdentifier.rsaEncryption | ||
spki.algorithmIdentifier.parameters = try ASN1Any(erasing: ASN1Null()) | ||
|
||
var serializer = DER.Serializer() | ||
try serializer.serialize(spki) | ||
|
||
return serializer.serializedBytes | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters