123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521 |
- //
- // CryptoSwift
- //
- // Copyright (C) 2014-2021 Marcin Krzyżanowski <marcin@krzyzanowskim.com>
- // This software is provided 'as-is', without any express or implied warranty.
- //
- // In no event will the authors be held liable for any damages arising from the use of this software.
- //
- // Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
- //
- // - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required.
- // - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
- // - This notice may not be removed or altered from any source or binary distribution.
- //
- import XCTest
- @testable import CryptoSwift
- final class ASN1Tests: XCTestCase {
- /// This test ensures that we get the same data out as we put in before and after encoding
- ///
- /// This test enforces that
- /// 1) The data provided to each of the `ASN1.Node`s is preserved across encoding and decoding.
- func testASN1NonDestructiveEncoding() throws {
- let arbitraryData = Data(hex: "0123456789")
- // Encode the serialized BigInteger
- let node: ASN1.Node = .sequence(nodes: [
- .integer(data: arbitraryData),
- .bitString(data: arbitraryData),
- .octetString(data: arbitraryData),
- .null,
- .objectIdentifier(data: arbitraryData)
- ])
- let encoded = ASN1.Encoder.encode(node)
- // Decode the Encoding
- let decoded = try ASN1.Decoder.decode(data: Data(encoded))
- guard case .sequence(let sequence) = decoded else {
- XCTFail("Failed to recover encoded SEQUENCE")
- return
- }
- XCTAssertEqual(sequence.count, 5)
- guard case .integer(let integerData) = sequence[0] else {
- XCTFail("Failed to recover encoded INTEGER")
- return
- }
- XCTAssertEqual(integerData, arbitraryData)
- guard case .bitString(let bitStringData) = sequence[1] else {
- XCTFail("Failed to recover encoded BITSTRING")
- return
- }
- XCTAssertEqual(bitStringData, arbitraryData)
- guard case .octetString(let octetData) = sequence[2] else {
- XCTFail("Failed to recover encoded OCTETSTRING")
- return
- }
- XCTAssertEqual(octetData, arbitraryData)
- guard case .null = sequence[3] else {
- XCTFail("Failed to recover encoded NULL")
- return
- }
- guard case .objectIdentifier(let objIDData) = sequence[4] else {
- XCTFail("Failed to recover encoded OBJECTIDENTIFIER")
- return
- }
- XCTAssertEqual(objIDData, arbitraryData)
- }
- /// The ASN1 Encoder / Decoder doesn't handle encoding / decoding Integers directly, it's your responsibility to accurately serialize your integers.
- /// - Note: In this example we're using BigInteger's serialization technique to encode / decode Integers, which isn't the default method for handling integers. https://www.strozhevsky.com/free_docs/asn1_by_simple_words.pdf
- ///
- /// This test enforces that
- /// 1) The data provided to the `ASN1.Node.integer` Node is preserved across encoding and decoding.
- func testASN1DecodePrimitiveInteger() throws {
- let tests = [
- 0,
- -0,
- 128,
- -128,
- 136,
- -136,
- 8388607,
- -8388607,
- 3409934108352718734,
- -3409934108352718734
- ]
- for test in tests {
- let number = BigInteger(test)
- // Encode the serialized Integer
- let encoded = ASN1.Encoder.encode(.integer(data: number.serialize()))
- // Ensure the Integer Prefix was added
- XCTAssertEqual(Array<UInt8>(arrayLiteral: 0x02), Array(encoded.prefix(1)))
- // Decode the Encoding
- let decoded = try ASN1.Decoder.decode(data: Data(encoded))
- guard case .integer(let num) = decoded else {
- XCTFail("Failed to recover encoded integer")
- return
- }
- // Ensure the original BigInteger was recovered
- XCTAssertEqual(BigInteger(num), number)
- }
- }
- /// Another test showing that Integers are stored as arbitrary data and the proper serialization and signage are the responsibilities of the user and their application.
- ///
- /// This test enforces that
- /// 1) The data provided to the `ASN1.Node.integer` Node is preserved across encoding and decoding.
- func testASN1DecodeLargeBigInteger() throws {
- // Because INTEGERS are stored as arbitrary data we should be able to store an integer that would otherwise overflow by using the BigInteger library
- let largeBigInt = BigInteger("1541235134652345698374107823450134507610354876134950342785028743653")
- // Encode the serialized BigInteger
- let encoded = ASN1.Encoder.encode(.integer(data: largeBigInt.serialize()))
- // Decode the Encoding
- let decoded = try ASN1.Decoder.decode(data: Data(encoded))
- guard case .integer(let num) = decoded else {
- XCTFail("Failed to recover encoded integer")
- return
- }
- // Ensure the original BigInteger was recovered
- XCTAssertEqual(BigInteger(num), largeBigInt)
- }
- /// This tests decodes an RSA Public Key from a Base64 DER Encoded representation
- ///
- /// This test enforces that
- /// 1) The decoding process yeilds the expected format.
- /// 2) The re-encoding of the data yeilds the exact same starting data.
- func testANS1DERDecodingPublicKey() throws {
- /// An example of an RSA Public Key ASN1 DER Encoding
- ///
- /// [IETF Spec RFC2313](https://datatracker.ietf.org/doc/html/rfc2313#section-7.1)
- /// ```
- /// =========================
- /// RSA PublicKey Structure
- /// =========================
- ///
- /// RSAPublicKey ::= SEQUENCE {
- /// modulus INTEGER, -- n
- /// publicExponent INTEGER, -- e
- /// }
- /// ```
- let publicDER = """
- MIGJAoGBAMGeZvIG84vyKAATwKkKz2g+PeNaZ63rxk/zEnLGxkMCVKnUZ6jPAtzYOKM24949yIhfxYBC/bOCPwRK4wbr4YyIx3WB2v+Zcqe8pRM/BThUpNIx3K2+jbJBhAopf1GXJ3i31RuiLMh9HWhxzkVamz1KnDjCuTZguCRRHIv+r3XTAgMBAAE=
- """
- guard let publicDERData = Data(base64Encoded: publicDER) else {
- XCTFail("Failed to convert base64 string into data for decoding.")
- return
- }
- let decoded = try ASN1.Decoder.decode(data: publicDERData)
- // Ensure the first node is of type Sequence
- guard case .sequence(let nodes) = decoded else {
- XCTFail("Expected the top level node to be a sequence and it wasn't")
- return
- }
- // Ensure there are two nodes within the top level sequence (our integers, n and e)
- XCTAssertEqual(nodes.count, 2)
- // Ensure that the first node within our sequence is of type Integer
- guard case .integer(let n) = nodes[0] else {
- XCTFail("Expected an integer within our sequence and it wasn't")
- return
- }
- // Ensure the second node within our sequence is of type Integer
- guard case .integer(let e) = nodes[1] else {
- XCTFail("Expected an integer within our sequence and it wasn't")
- return
- }
- // Ensure that n contains the data we expected
- XCTAssertEqual(n.toHexString(), "00c19e66f206f38bf2280013c0a90acf683e3de35a67adebc64ff31272c6c6430254a9d467a8cf02dcd838a336e3de3dc8885fc58042fdb3823f044ae306ebe18c88c77581daff9972a7bca5133f053854a4d231dcadbe8db241840a297f51972778b7d51ba22cc87d1d6871ce455a9b3d4a9c38c2b93660b824511c8bfeaf75d3")
- // Ensure that e contains the data we expected
- XCTAssertEqual(e.toHexString(), "010001") // 65537
- // Re Encode the data
- let asn1: ASN1.Node = .sequence(nodes: [
- .integer(data: n),
- .integer(data: e)
- ])
- let encoded = ASN1.Encoder.encode(asn1)
- // Ensure the re-encoded data matches the original exactly
- XCTAssertEqual(Data(encoded), publicDERData)
- XCTAssertEqual(encoded, publicDERData.bytes)
- XCTAssertEqual(encoded.toBase64(), publicDER)
- }
- /// This tests decodes an RSA Private Key from a Base64 DER Encoded representation
- ///
- /// This test enforces that
- /// 1) The decoding process yeilds the expected format.
- /// 2) The re-encoding of the data yeilds the exact same starting data.
- func testANS1DERDecodingPrivateKey() throws {
- /// An example of an RSA Private Key ASN1 DER Encoding
- ///
- /// [IETF Spec RFC2313](https://datatracker.ietf.org/doc/html/rfc2313#section-7.2)
- /// ```
- /// ==========================
- /// RSA PrivateKey Structure
- /// ==========================
- ///
- /// RSAPrivateKey ::= SEQUENCE {
- /// version Version,
- /// modulus INTEGER, -- n
- /// publicExponent INTEGER, -- e
- /// privateExponent INTEGER, -- d
- /// prime1 INTEGER, -- p
- /// prime2 INTEGER, -- q
- /// exponent1 INTEGER, -- d mod (p-1)
- /// exponent2 INTEGER, -- d mod (q-1)
- /// coefficient INTEGER, -- (inverse of q) mod p
- /// otherPrimeInfos OtherPrimeInfos OPTIONAL
- /// }
- /// ```
- let privateDER = """
- MIICXQIBAAKBgQDBnmbyBvOL8igAE8CpCs9oPj3jWmet68ZP8xJyxsZDAlSp1GeozwLc2DijNuPePciIX8WAQv2zgj8ESuMG6+GMiMd1gdr/mXKnvKUTPwU4VKTSMdytvo2yQYQKKX9Rlyd4t9UboizIfR1occ5FWps9Spw4wrk2YLgkURyL/q910wIDAQABAoGAGJkNLxZe/pqHJmtcAJ3U98NgjW/A2EGp8iJJZ7eFHKJBK0pG2RVjobb+iw3AKU3kGh9AsijQnmufoeX5rblt7/ojgpfVhS7NHsKCi8Nx7U92bNnP0RP4mogpvzGWVknUdv6jW7dX83FKgEywbNKa5CPQk1XinqXL33gNjWdOh/ECQQDjdE4kNdVwKA59ddWRShvJiOMOG8+TjE5HvcZzKQ+UMlBwbknL5tIJE7KnN9ZEfNihVmyrMAzJAfe2PCyZAip/AkEA2esFkG+ScgeVYlGrUqrqUkvzj1j6F8R+8rGvCjq2WnDL8TzO7NoT7qivW/+6E9osX1WwWAtj/84eN7dvLLxCrQJBAN7GomZq58MzKIYPLH9iI3cwAJtn99ZfHKi9oipW9DBFW23TR6pTSDKlvVx0nwNzeEYFPOgqZstVhwZRR6kRawcCQHx/u0QTmjUvg/cR9bFbGFhAMDxbdzaQ+n4paXmMpZXyD3IZbZb/2JdnJBiJd4PUB7nHuOH0UANbfQQT9p42SFkCQQCcdFRTZEZv5TjmcUn0GBUzRmnswiRc1YEg81DSDlvD3dEIVSl6PLkzcNNItrgD5SfC5MxCv6PIUlJVhnkavEjS
- """
- guard let privateDERData = Data(base64Encoded: privateDER) else {
- XCTFail("Failed to convert base64 string into data for decoding.")
- return
- }
- let decoded = try ASN1.Decoder.decode(data: privateDERData)
- // Ensure the first Node is of type SEQUENCE
- guard case .sequence(let nodes) = decoded else {
- XCTFail("Expected the top level node to be a sequence and it wasn't")
- return
- }
- // Ensure there are nine (9) Nodes within the top level SEQUENCE
- XCTAssertEqual(nodes.count, 9)
- // Deconstruct the parameters
- guard case .integer(let version) = nodes[0] else {
- XCTFail("Expected an integer within our sequence and it wasn't")
- return
- }
- XCTAssertEqual(version, Data(hex: "00"))
- guard case .integer(let n) = nodes[1] else {
- XCTFail("Expected an integer within our sequence and it wasn't")
- return
- }
- XCTAssertEqual(n, Data(hex: "00c19e66f206f38bf2280013c0a90acf683e3de35a67adebc64ff31272c6c6430254a9d467a8cf02dcd838a336e3de3dc8885fc58042fdb3823f044ae306ebe18c88c77581daff9972a7bca5133f053854a4d231dcadbe8db241840a297f51972778b7d51ba22cc87d1d6871ce455a9b3d4a9c38c2b93660b824511c8bfeaf75d3"))
- guard case .integer(let e) = nodes[2] else {
- XCTFail("Expected an integer within our sequence and it wasn't")
- return
- }
- XCTAssertEqual(e, Data(hex: "010001"))
- guard case .integer(let d) = nodes[3] else {
- XCTFail("Expected an integer within our sequence and it wasn't")
- return
- }
- XCTAssertEqual(d, Data(hex: "18990d2f165efe9a87266b5c009dd4f7c3608d6fc0d841a9f2224967b7851ca2412b4a46d91563a1b6fe8b0dc0294de41a1f40b228d09e6b9fa1e5f9adb96deffa238297d5852ecd1ec2828bc371ed4f766cd9cfd113f89a8829bf31965649d476fea35bb757f3714a804cb06cd29ae423d09355e29ea5cbdf780d8d674e87f1"))
- guard case .integer(let p) = nodes[4] else {
- XCTFail("Expected an integer within our sequence and it wasn't")
- return
- }
- XCTAssertEqual(p, Data(hex: "00e3744e2435d570280e7d75d5914a1bc988e30e1bcf938c4e47bdc673290f943250706e49cbe6d20913b2a737d6447cd8a1566cab300cc901f7b63c2c99022a7f"))
- guard case .integer(let q) = nodes[5] else {
- XCTFail("Expected an integer within our sequence and it wasn't")
- return
- }
- XCTAssertEqual(q, Data(hex: "00d9eb05906f927207956251ab52aaea524bf38f58fa17c47ef2b1af0a3ab65a70cbf13cceecda13eea8af5bffba13da2c5f55b0580b63ffce1e37b76f2cbc42ad"))
- guard case .integer(let exp1) = nodes[6] else {
- XCTFail("Expected an integer within our sequence and it wasn't")
- return
- }
- XCTAssertEqual(exp1, Data(hex: "00dec6a2666ae7c33328860f2c7f62237730009b67f7d65f1ca8bda22a56f430455b6dd347aa534832a5bd5c749f03737846053ce82a66cb5587065147a9116b07"))
- guard case .integer(let exp2) = nodes[7] else {
- XCTFail("Expected an integer within our sequence and it wasn't")
- return
- }
- XCTAssertEqual(exp2, Data(hex: "7c7fbb44139a352f83f711f5b15b185840303c5b773690fa7e2969798ca595f20f72196d96ffd897672418897783d407b9c7b8e1f450035b7d0413f69e364859"))
- guard case .integer(let coefficient) = nodes[8] else {
- XCTFail("Expected an integer within our sequence and it wasn't")
- return
- }
- XCTAssertEqual(coefficient, Data(hex: "009c74545364466fe538e67149f41815334669ecc2245cd58120f350d20e5bc3ddd10855297a3cb93370d348b6b803e527c2e4cc42bfa3c852525586791abc48d2"))
- // Ensure re-encoding the data yeilds the exact same starting data
- let asn: ASN1.Node = .sequence(nodes: [
- .integer(data: version),
- .integer(data: n),
- .integer(data: e),
- .integer(data: d),
- .integer(data: p),
- .integer(data: q),
- .integer(data: exp1),
- .integer(data: exp2),
- .integer(data: coefficient)
- ])
- // Encode the ASN1 Nodes
- let encodedData = ASN1.Encoder.encode(asn)
- // Ensure the re-encoded data matches the original data exactly
- XCTAssertEqual(Data(encodedData), privateDERData)
- XCTAssertEqual(encodedData, privateDERData.bytes)
- XCTAssertEqual(encodedData.toBase64(), privateDER.replacingOccurrences(of: "\n", with: ""))
- }
- /// This tests decodes an Encrypted RSA Private Key from a Base64 PEM Encoded representation
- ///
- /// This test enforces that
- /// 1) The decoding process yeilds the expected format.
- /// 2) The re-encoding of the data yeilds the exact same starting data.
- func testASN1DecodingEncryptedPEM() throws {
- /// ==========================
- /// Encrypted PEM Structure
- /// ==========================
- ///
- /// EncryptedPrivateKey ::= SEQUENCE {
- ///
- /// PEMStructure ::= SEQUENCE {
- /// pemObjID OBJECTIDENTIFIER
- ///
- /// EncryptionAlgorithms ::= SEQUENCE {
- ///
- /// PBKDFAlgorithms ::= SEQUENCE {
- /// pbkdfObjID OBJECTIDENTIFIER
- /// PBKDFParams ::= SEQUENCE {
- /// salt OCTETSTRING,
- /// iterations INTEGER
- /// }
- /// },
- ///
- /// CIPHERAlgorithms ::= SEQUENCE {
- /// cipherObjID OBJECTIDENTIFIER,
- /// iv OCTETSTRING
- /// }
- /// }
- /// }
- /// encryptedData OCTETSTRING
- /// }
- ///
- /// /*
- /// * Generated with
- /// * openssl genpkey -algorithm RSA
- /// * -pkeyopt rsa_keygen_bits:1024
- /// * -pkeyopt rsa_keygen_pubexp:65537
- /// * -out foo.pem
- /// * openssl pkcs8 -in foo.pem -topk8 -v2 aes-128-cbc -passout pass:mypassword
- /// */
- let encryptedPEMFormat = """
- MIICzzBJBgkqhkiG9w0BBQ0wPDAbBgkqhkiG9w0BBQwwDgQIP5QK2RfqUl4CAggA
- MB0GCWCGSAFlAwQBAgQQj3OyM9gnW2dd/eRHkxjGrgSCAoCpM5GZB0v27cxzZsGc
- O4/xqgwB0c/bSJ6QogtYU2KVoc7ZNQ5q9jtzn3I4ONvneOkpm9arzYz0FWnJi2C3
- BPiF0D1NkfvjvMLv56bwiG2A1oBECacyAb2pXYeJY7SdtYKvcbgs3jx65uCm6TF2
- BylteH+n1ewTQN9DLfASp1n81Ajq9lQGaK03SN2MUtcAPp7N9gnxJrlmDGeqlPRs
- KpQYRcot+kE6Ew8a5jAr7mAxwpqvr3SM4dMvADZmRQsM4Uc/9+YMUdI52DG87EWc
- 0OUB+fnQ8jw4DZgOE9KKM5/QTWc3aEw/dzXr/YJsrv01oLazhqVHnEMG0Nfr0+DP
- q+qac1AsCsOb71VxaRlRZcVEkEfAq3gidSPD93qmlDrCnmLYTilcLanXUepda7ez
- qhjkHtpwBLN5xRZxOn3oUuLGjk8VRwfmFX+RIMYCyihjdmbEDYpNUVkQVYFGi/F/
- 1hxOyl9yhGdL0hb9pKHH10GGIgoqo4jSTLlb4ennihGMHCjehAjLdx/GKJkOWShy
- V9hj8rAuYnRNb+tUW7ChXm1nLq14x9x1tX0ciVVn3ap/NoMkbFTr8M3pJ4bQlpAn
- wCT2erYqwQtgSpOJcrFeph9TjIrNRVE7Zlmr7vayJrB/8/oPssVdhf82TXkna4fB
- PcmO0YWLa117rfdeNM/Duy0ThSdTl39Qd+4FxqRZiHjbt+l0iSa/nOjTv1TZ/QqF
- wqrO6EtcM45fbFJ1Y79o2ptC2D6MB4HKJq9WCt064/8zQCVx3XPbb3X8Z5o/6koy
- ePGbz+UtSb9xczvqpRCOiFLh2MG1dUgWuHazjOtUcVWvilKnkjCMzZ9s1qG0sUDj
- nPyn
- """
- guard let pemData = Data(base64Encoded: encryptedPEMFormat.replacingOccurrences(of: "\n", with: "")) else {
- XCTFail("Failed to convert base64 string to data")
- return
- }
- let asn = try ASN1.Decoder.decode(data: pemData)
- // Ensure the first node is a Sequence
- guard case .sequence(let encryptedPEMWrapper) = asn else {
- XCTFail("Expected top level Node to be a SEQUENCE object")
- return
- }
- // Ensure the first Sequence contains exactly 2 nodes (another Sequence and our OctetString of encrypted data)
- XCTAssertEqual(encryptedPEMWrapper.count, 2)
- // Ensure the first node within the top level sequence is another sequence
- guard case .sequence(let encryptionInfoWrapper) = encryptedPEMWrapper[0] else {
- XCTFail("Expected the first Node within our top level SEQUENCE to be a SEQUENCE object and it wasn't")
- return
- }
- // Ensure this sequence contains exactly two nodes (the PEMs ObjectIdentifier and another sequence that houses the encryption algorithms)
- XCTAssertEqual(encryptionInfoWrapper.count, 2)
- // Ensure the first Node is the PEM's OBJECTIDENTIFIER Node
- guard case .objectIdentifier(let pemObjID) = encryptionInfoWrapper[0] else {
- XCTFail("Expected an OBJECTIDENTIFIER and it wasn't")
- return
- }
- // Ensure the second Node is another SEQUENCE Node
- guard case .sequence(let encryptionAlgorithmsWrapper) = encryptionInfoWrapper[1] else {
- XCTFail("Expected another SEQUENCE Node and it wasn't")
- return
- }
- // Ensure this sequence contains exactly two nodes (the PEMs ObjectIdentifier and another sequence that houses the encryption algorithms)
- XCTAssertEqual(encryptionAlgorithmsWrapper.count, 2)
- // Ensure the first Node is another SEQUENCE Node
- guard case .sequence(let pbkdfAlgorithmWrapper) = encryptionAlgorithmsWrapper[0] else {
- XCTFail("Expected another SEQUENCE Node and it wasn't")
- return
- }
- // Ensure this sequence contains exactly two nodes (the PBKDF ObjectIdentifier and another sequence that houses the PBKDF params)
- XCTAssertEqual(pbkdfAlgorithmWrapper.count, 2)
- guard case .objectIdentifier(let pbkdfObjID) = pbkdfAlgorithmWrapper[0] else {
- XCTFail("Expected an OBJECTIDENTIFIER and it wasn't")
- return
- }
- guard case .sequence(let pbkdfParamsWrapper) = pbkdfAlgorithmWrapper[1] else {
- XCTFail("Expected an OCTETSTRING and it wasn't")
- return
- }
- // Ensure this sequence contains exactly two nodes (the PBKDF Salt as an OCTETSTRING and the PBKDF Iterations as an INTEGER)
- XCTAssertEqual(pbkdfParamsWrapper.count, 2)
- guard case .octetString(let pbkdfSalt) = pbkdfParamsWrapper[0] else {
- XCTFail("Expected an OCTETSTRING and it wasn't")
- return
- }
- guard case .integer(let pbkdfIterations) = pbkdfParamsWrapper[1] else {
- XCTFail("Expected an INTEGER and it wasn't")
- return
- }
- // Ensure the second Node is another SEQUENCE Node
- guard case .sequence(let cipherAlgorithmWrapper) = encryptionAlgorithmsWrapper[1] else {
- XCTFail("Expected another SEQUENCE Node and it wasn't")
- return
- }
- // Ensure this sequence contains exactly two nodes (the CIPHER ObjectIdentifier and an OCTETSTRING that contains the CIPHERs InitialVector)
- XCTAssertEqual(cipherAlgorithmWrapper.count, 2)
- guard case .objectIdentifier(let cipherObjID) = cipherAlgorithmWrapper[0] else {
- XCTFail("Expected an OBJECTIDENTIFIER and it wasn't")
- return
- }
- guard case .octetString(let cipherInitialVector) = cipherAlgorithmWrapper[1] else {
- XCTFail("Expected an OCTETSTRING and it wasn't")
- return
- }
- // Ensure the last (2nd) Node in the top level SEQUENCE Node is an OCTETSTRING that contains the encrypted key data
- guard case .octetString(let encryptedData) = encryptedPEMWrapper[1] else {
- XCTFail("Expected the last Node in the first SEQUENCE Node to be an OCTETSTRING and it wasn't")
- return
- }
- // Now lets ensure we can re encode the object and get back the exact same data
- let nodes: ASN1.Node = .sequence(nodes: [
- .sequence(nodes: [
- .objectIdentifier(data: pemObjID),
- .sequence(nodes: [
- .sequence(nodes: [
- .objectIdentifier(data: pbkdfObjID),
- .sequence(nodes: [
- .octetString(data: pbkdfSalt),
- .integer(data: pbkdfIterations)
- ])
- ]),
- .sequence(nodes: [
- .objectIdentifier(data: cipherObjID),
- .octetString(data: cipherInitialVector)
- ])
- ])
- ]),
- .octetString(data: encryptedData)
- ])
- // Encode the ASN1 Nodes
- let encodedData = ASN1.Encoder.encode(nodes)
- // Ensure the re-encoded data matches the original data exactly
- XCTAssertEqual(Data(encodedData), pemData)
- XCTAssertEqual(encodedData, pemData.bytes)
- XCTAssertEqual(encodedData.toBase64(), encryptedPEMFormat.replacingOccurrences(of: "\n", with: ""))
- }
- static let allTests = [
- ("testASN1NonDestructiveEncoding", testASN1NonDestructiveEncoding),
- ("testASN1DecodePrimitiveInteger", testASN1DecodePrimitiveInteger),
- ("testASN1DecodeLargeBigInteger", testASN1DecodeLargeBigInteger),
- ("testANS1DERDecodingPublicKey", testANS1DERDecodingPublicKey),
- ("testANS1DERDecodingPrivateKey", testANS1DERDecodingPrivateKey),
- ("testASN1DecodingEncryptedPEM", testASN1DecodingEncryptedPEM)
- ]
- }
|