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.
		
		
		
		
		
			
		
			
				
	
	
		
			78 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			Swift
		
	
			
		
		
	
	
			78 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			Swift
		
	
// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
 | 
						|
 | 
						|
import Foundation
 | 
						|
import GRDB
 | 
						|
import Sodium
 | 
						|
import SessionUtilitiesKit
 | 
						|
 | 
						|
extension MessageSender {
 | 
						|
    internal static func encryptWithSessionProtocol(
 | 
						|
        _ db: Database,
 | 
						|
        plaintext: Data,
 | 
						|
        for recipientHexEncodedX25519PublicKey: String,
 | 
						|
        using dependencies: SMKDependencies = SMKDependencies()
 | 
						|
    ) throws -> Data {
 | 
						|
        guard let userEd25519KeyPair: KeyPair = Identity.fetchUserEd25519KeyPair(db) else {
 | 
						|
            throw MessageSenderError.noUserED25519KeyPair
 | 
						|
        }
 | 
						|
        
 | 
						|
        let recipientX25519PublicKey = Data(hex: recipientHexEncodedX25519PublicKey.removingIdPrefixIfNeeded())
 | 
						|
        
 | 
						|
        let verificationData = plaintext + Data(userEd25519KeyPair.publicKey) + recipientX25519PublicKey
 | 
						|
        guard let signature = dependencies.sign.signature(message: Bytes(verificationData), secretKey: userEd25519KeyPair.secretKey) else {
 | 
						|
            throw MessageSenderError.signingFailed
 | 
						|
        }
 | 
						|
        
 | 
						|
        let plaintextWithMetadata = plaintext + Data(userEd25519KeyPair.publicKey) + Data(signature)
 | 
						|
        guard let ciphertext = dependencies.box.seal(message: Bytes(plaintextWithMetadata), recipientPublicKey: Bytes(recipientX25519PublicKey)) else {
 | 
						|
            throw MessageSenderError.encryptionFailed
 | 
						|
        }
 | 
						|
        
 | 
						|
        return Data(ciphertext)
 | 
						|
    }
 | 
						|
    
 | 
						|
    internal static func encryptWithSessionBlindingProtocol(
 | 
						|
        _ db: Database,
 | 
						|
        plaintext: Data,
 | 
						|
        for recipientBlindedId: String,
 | 
						|
        openGroupPublicKey: String,
 | 
						|
        using dependencies: SMKDependencies = SMKDependencies()
 | 
						|
    ) throws -> Data {
 | 
						|
        guard SessionId.Prefix(from: recipientBlindedId) == .blinded else {
 | 
						|
            throw MessageSenderError.signingFailed
 | 
						|
        }
 | 
						|
        guard let userEd25519KeyPair: KeyPair = Identity.fetchUserEd25519KeyPair(db) else {
 | 
						|
            throw MessageSenderError.noUserED25519KeyPair
 | 
						|
        }
 | 
						|
        guard let blindedKeyPair = dependencies.sodium.blindedKeyPair(serverPublicKey: openGroupPublicKey, edKeyPair: userEd25519KeyPair, genericHash: dependencies.genericHash) else {
 | 
						|
            throw MessageSenderError.signingFailed
 | 
						|
        }
 | 
						|
        
 | 
						|
        let recipientBlindedPublicKey = Data(hex: recipientBlindedId.removingIdPrefixIfNeeded())
 | 
						|
        
 | 
						|
        /// Step one: calculate the shared encryption key, sending from A to B
 | 
						|
        guard let enc_key: Bytes = dependencies.sodium.sharedBlindedEncryptionKey(
 | 
						|
            secretKey: userEd25519KeyPair.secretKey,
 | 
						|
            otherBlindedPublicKey: recipientBlindedPublicKey.bytes,
 | 
						|
            fromBlindedPublicKey: blindedKeyPair.publicKey,
 | 
						|
            toBlindedPublicKey: recipientBlindedPublicKey.bytes,
 | 
						|
            genericHash: dependencies.genericHash
 | 
						|
        ) else {
 | 
						|
            throw MessageSenderError.signingFailed
 | 
						|
        }
 | 
						|
        
 | 
						|
        /// Inner data: msg || A   (i.e. the sender's ed25519 master pubkey, *not* kA blinded pubkey)
 | 
						|
        let innerBytes: Bytes = (plaintext.bytes + userEd25519KeyPair.publicKey)
 | 
						|
        
 | 
						|
        /// Encrypt using xchacha20-poly1305
 | 
						|
        let nonce: Bytes = dependencies.nonceGenerator24.nonce()
 | 
						|
        
 | 
						|
        guard let ciphertext = dependencies.aeadXChaCha20Poly1305Ietf.encrypt(message: innerBytes, secretKey: enc_key, nonce: nonce) else {
 | 
						|
            throw MessageSenderError.encryptionFailed
 | 
						|
        }
 | 
						|
        
 | 
						|
        /// data = b'\x00' + ciphertext + nonce
 | 
						|
        return Data(Bytes(arrayLiteral: 0) + ciphertext + nonce)
 | 
						|
    }
 | 
						|
}
 |