mirror of https://github.com/oxen-io/session-ios
				
				
				
			
			You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
	
	
		
			85 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			Swift
		
	
		
		
			
		
	
	
			85 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			Swift
		
	
| 
											3 years ago
										 | // Copyright © 2022 Rangeproof Pty Ltd. All rights reserved. | ||
|  | 
 | ||
|  | import Foundation | ||
|  | import Sodium | ||
|  | import SessionUtilitiesKit | ||
|  | 
 | ||
|  | extension SnodeAPI { | ||
|  |     public class ONSResolveResponse: SnodeResponse { | ||
|  |         private struct Result: Codable { | ||
|  |             enum CodingKeys: String, CodingKey { | ||
|  |                 case nonce | ||
|  |                 case encryptedValue = "encrypted_value" | ||
|  |             } | ||
|  |              | ||
|  |             fileprivate let nonce: String? | ||
|  |             fileprivate let encryptedValue: String | ||
|  |         } | ||
|  |          | ||
|  |         enum CodingKeys: String, CodingKey { | ||
|  |             case result | ||
|  |         } | ||
|  |          | ||
|  |         private let result: Result | ||
|  |          | ||
|  |         // MARK: - Initialization | ||
|  |          | ||
|  |         required init(from decoder: Decoder) throws { | ||
|  |             let container: KeyedDecodingContainer<CodingKeys> = try decoder.container(keyedBy: CodingKeys.self) | ||
|  |              | ||
|  |             result = try container.decode(Result.self, forKey: .result) | ||
|  |              | ||
|  |             try super.init(from: decoder) | ||
|  |         } | ||
|  |          | ||
|  |         // MARK: - Convenience | ||
|  |          | ||
|  |         func sessionId(sodium: Sodium, nameBytes: [UInt8], nameHashBytes: [UInt8]) throws -> String { | ||
|  |             let ciphertext: [UInt8] = Data(hex: result.encryptedValue).bytes | ||
|  |              | ||
|  |             // Handle old Argon2-based encryption used before HF16 | ||
|  |             guard let hexEncodedNonce: String = result.nonce else { | ||
|  |                 let salt: [UInt8] = Data(repeating: 0, count: sodium.pwHash.SaltBytes).bytes | ||
|  |                  | ||
|  |                 guard | ||
|  |                     let key: [UInt8] = sodium.pwHash.hash( | ||
|  |                         outputLength: sodium.secretBox.KeyBytes, | ||
|  |                         passwd: nameBytes, | ||
|  |                         salt: salt, | ||
|  |                         opsLimit: sodium.pwHash.OpsLimitModerate, | ||
|  |                         memLimit: sodium.pwHash.MemLimitModerate, | ||
|  |                         alg: .Argon2ID13 | ||
|  |                     ) | ||
|  |                 else { throw SnodeAPIError.hashingFailed } | ||
|  |                  | ||
|  |                 let nonce: [UInt8] = Data(repeating: 0, count: sodium.secretBox.NonceBytes).bytes | ||
|  |                  | ||
|  |                 guard let sessionIdAsData: [UInt8] = sodium.secretBox.open(authenticatedCipherText: ciphertext, secretKey: key, nonce: nonce) else { | ||
|  |                     throw SnodeAPIError.decryptionFailed | ||
|  |                 } | ||
|  | 
 | ||
|  |                 return sessionIdAsData.toHexString() | ||
|  |             } | ||
|  |              | ||
|  |             let nonceBytes: [UInt8] = Data(hex: hexEncodedNonce).bytes | ||
|  | 
 | ||
|  |             // xchacha-based encryption | ||
|  |             // key = H(name, key=H(name)) | ||
|  |             guard let key: [UInt8] = sodium.genericHash.hash(message: nameBytes, key: nameHashBytes) else { | ||
|  |                 throw SnodeAPIError.hashingFailed | ||
|  |             } | ||
|  |             guard | ||
|  |                 // Should always be equal in practice | ||
|  |                 ciphertext.count >= (SessionId.byteCount + sodium.aead.xchacha20poly1305ietf.ABytes), | ||
|  |                 let sessionIdAsData = sodium.aead.xchacha20poly1305ietf.decrypt( | ||
|  |                     authenticatedCipherText: ciphertext, | ||
|  |                     secretKey: key, | ||
|  |                     nonce: nonceBytes | ||
|  |                 ) | ||
|  |             else { throw SnodeAPIError.decryptionFailed } | ||
|  | 
 | ||
|  |             return sessionIdAsData.toHexString() | ||
|  |         } | ||
|  |     } | ||
|  | } |