Building Secure AI Inference and Training Pipelines Using Homomorphic Encryption in Financial and Healthcare Domains: Strategies for Maximizing Data Privacy and Model Security

The use of AI with sensitive data in finance and healthcare brings innovation but also serious privacy and security challenges. This article introduces Homomorphic Encryption (HE) technology to enable AI model inference and training directly on encrypted data, thereby presenting practical pipeline construction strategies to maximize the potential of artificial intelligence without the risk of data breaches.

1. The Challenge / Context

Financial institutions handle highly sensitive personal financial data such as customer transaction history, credit scores, and asset information. The healthcare sector processes personal health information directly related to life, including patient medical records, genomic data, and biometric data. This data is essential for innovative AI-based services like fraud detection, personalized financial product recommendations, disease diagnosis assistance, and drug discovery. However, such data is subject to strict regulations (e.g., GDPR, CCPA, domestic personal information protection laws, MyData), and data breaches can lead to enormous financial and social damage. Most existing AI pipelines learn and infer based on plaintext data, which poses a risk of security vulnerabilities at every stage of data processing. This problem is exacerbated in cloud environments or multi-party collaborations. Therefore, a fundamental solution is urgently needed to fully leverage the potential of AI without compromising data privacy and security.

2. Deep Dive: Homomorphic Encryption (HE)

Homomorphic Encryption is a magical technology where performing operations (such as addition, multiplication) directly on encrypted data yields the same result as performing the same operations on the unencrypted original data and then encrypting the outcome. In simple terms, it's the concept of 'manipulating contents inside a locked box without taking them out.'

HE is broadly categorized into three types:

  • Partially Homomorphic Encryption (PHE): Allows an infinite number of operations of only one type (either addition or multiplication). (e.g., Paillier, RSA)
  • Somewhat Homomorphic Encryption (SHE): Allows both addition and multiplication but with a limited number of operations. (e.g., BFV, BGV, CKKS)
  • Fully Homomorphic Encryption (FHE): Allows an unlimited number of both addition and multiplication operations. (e.g., Gentry's scheme, TFHE, CKKS with bootstrapping)

AI model inference and training require a combination of addition and multiplication operations, so Somewhat Homomorphic Encryption (SHE) or Fully Homomorphic Encryption (FHE) methods are generally used. Especially for AI models with many floating-point operations, the CKKS scheme, which supports approximate computation, is primarily considered. The core of HE is that when a data provider encrypts their data and sends it to a server, the server processes this encrypted data through an AI model without decrypting it, and returns the result also in an encrypted state. Subsequently, only the data provider can decrypt the result with their private key. This fundamentally blocks the possibility of a third party viewing the data in plaintext, thereby maximizing both data privacy and model security simultaneously.

3. Step-by-Step Guide / Implementation

Building a secure AI inference and training pipeline using homomorphic encryption is complex but involves several key steps. Here, we will explain it using a simple linear regression model inference as an example, leveraging Python-based HE libraries (e.g., PySEAAL binding for Microsoft SEAL).

Step 1: Homomorphic Encryption Library Selection and Environment Setup

You need to choose an HE library that fits your project requirements from various options. Generally, factors like speed, supported operation types, and difficulty are considered. Here, we implement the CKKS scheme, suitable for floating-point operations, via PySEAAL.


    # PySEAAL 설치 (필요시)
    # pip install pyseal
    
    from seal import *
    # seal_helper는 SEAL 컨텍스트 파라미터를 출력하는 함수 등을 포함할 수 있습니다.
    # 이 예제에서는 편의상 print_parameters 함수를 직접 정의한다고 가정합니다.
    
    def print_parameters(context):
        parms = context.get_context_data(context.first_context_data().parms_id()).parms()
        print(f"Scheme Type: {parms.scheme()}")
        print(f"Poly Modulus Degree: {parms.poly_modulus_degree()}")
        print(f"Coeff Modulus: {parms.coeff_modulus().size()} primes")
        print(f"Global Scale (CKKS): {pow(2.0, parms.coeff_modulus().max())}")
        print("---")
    
    def setup_seal_context():
        # CKKS 파라미터 설정
        parms = EncryptionParameters(SCHEME_TYPE.CKKS)
        poly_modulus_degree = 8192 # 다항식 모듈러스 차수 (보안 레벨 및 성능에 영향)
        parms.set_poly_modulus_degree(poly_modulus_degree)
        
        # 계수 모듈러스 설정. CKKS는 연산 시 노이즈가 증가하므로,
        # 연산 깊이에 따라 적절한 크기의 프라임 체인을 설정해야 합니다.
        # 예: 60비트, 40비트, 40비트, 60비트 프라임 (4단계 연산 가능 가정)
        parms.set_coeff_modulus(CoeffModulus.Create(poly_modulus_degree, [60, 40, 40, 60]))
    
        context = SEALContext(parms)
        print_parameters(context) # SEAL 컨텍스트 파라미터 출력
        if not context.parameters_set():
            raise Exception("SEAL context could not be created. Check parameters.")
        return context
    
    context = setup_seal_context()
    

Personal Tip: The values in `CoeffModulus.Create` determine the security level and the operable depth. Since noise increases during CKKS operations, a larger coefficient modulus must be set as the number of operations increases. This leads to a decrease in operation speed, so it is crucial to accurately predict the model's complexity and the required operational depth. These values are closely related to the approximation of activation functions, the number of layers, and so on, in the model.

Step 2: Key Generation and Encoder/Encryptor/Decryptor Setup

Homomorphic encryption systems use public key/private key pairs. The encoder converts ordinary numbers into a format that HE can process, and the encryptor encrypts them. The decryptor converts the encrypted results back into ordinary numbers.


    keygen = KeyGenerator(context)
    public_key = keygen.public_key()
    secret_key = keygen.secret_key()
    relin_keys = keygen.relin_keys() # 재선형화 키 (곱셈 연산 후 필요)
    # Galois Keys는 rotate_vector와 같은 슬롯 재정렬 연산에 필요합니다.
    galois_keys = keygen.galois_keys() 
    
    encoder = CKKSEncoder(context)
    encryptor = Encryptor(context, public_key)
    decryptor = Decryptor(context, secret_key)
    
    scale = pow(2.0, 40) # CKKS 스케일 설정 (정밀도와 오버플로우 방지)
    

Step 3: AI Model Parameter Encryption and Data Encryption

AI model parameters such as weights and biases, and input data for inference, are encrypted. Generally, model parameters are pre-encrypted on the server side, and input data is encrypted on the client side and sent to the server. Here, we use a simple linear regression model y = Wx + b with a single feature as an example.


    # AI 모델 파라미터 (단일 가중치 W, 단일 편향 b)
    model_weight_W = 0.5
    model_bias_b = 0.1
    
    # 모델 파라미터 암호화 (서버에서 수행)
    # CKKS 인코더는 벡터를 슬롯에 인코딩할 수 있습니다. 여기서는 단일 값을 벡터로 취급.
    encoded_weight = encoder.encode([model_weight_W], scale)
    encrypted_weight = encryptor.encrypt(encoded_weight)
    
    encoded_bias = encoder.encode([model_bias_b], scale)
    encrypted_bias = encryptor.encrypt(encoded_bias)
    
    # 클라이언트 입력 데이터 (단일 특징 x)
    client_input_x = 1.2
    
    # 클라이언트에서 입력 데이터 암호화 후 서버로 전송
    encoded_input_x = encoder.encode([client_input_x], scale)
    encrypted_input_x = encryptor.encrypt(encoded_input_x)
    

Step 4: AI Model Inference in Encrypted State

The server performs operations directly on the encrypted input data and encrypted model parameters without decryption. The Homomorphic Encryption Evaluator plays this role.


    evaluator = Evaluator(context)
    
    # Wx 계산 (Multiply)
    # encrypted_weight (Ciphertext of [W]) * encrypted_input_x (Ciphertext of [x])
    encrypted_wx = evaluator.multiply(encrypted_weight, encrypted_input_x)
    
    # 곱셈 후 노이즈 증가로 인해 재선형화 필요
    evaluator.relinearize_inplace(encrypted_wx, relin_keys) 
    
    # 스케일 조정 (노이즈 관리 및 정밀도 유지). 다음 연산을 위해 스케일을 낮춥니다.
    evaluator.rescale_to_next_inplace(encrypted_wx) 
    
    # Wx + b 계산 (Add)
    # 스케일을 맞추기 위해 encrypted_bias도 리스케일될 수 있습니다.
    # SEAL은 연산 전에 자동으로 스케일을 맞추거나 에러를 발생시킬 수 있습니다.
    # 여기서는 encrypted_wx의 스케일에 맞춰 encrypted_bias를 다시 인코딩하거나
    # SEAL의 automatic rescaling 기능을 이용해야 합니다.
    # 간단화를 위해 현재 encrypted_bias도 동일한 스케일을 가진다고 가정합니다.
    
    # 만약 스케일이 다르다면:
    # evaluator.rescale_to_next_inplace(encrypted_bias) # encrypted_wx의 스케일에 맞춤
    # evaluator.match_level_inplace(encrypted_bias, encrypted_wx) # 레벨 맞춤
    
    encrypted_result = evaluator.add(encrypted_wx, encrypted_bias)
    

Note: In actual multi-dimensional vector operations (e.g., deep learning layers), the concept of CKKS slots is utilized to efficiently compress multiple data points into a single ciphertext, and functions like `rotate_vector` are used to perform vector dot products, etc. In such cases, `GaloisKeys` are additionally required. The code above is a single-value example for illustrative purposes, and actual pipelines require more complex operation management.

Step 5: Encrypted Result Transmission and Decryption

The server transmits the encrypted inference result to the client, and the client decrypts it with their private key.


    # 서버 -> 클라이언트로 encrypted_result 전송 (이 단계는 네트워크 통신을 의미)
    # 클라이언트에서 암호화된 결과 수신 후 복호화
    decrypted_result_encoded = decryptor.decrypt(encrypted_result)
    
    # CKKS는 근사치를 반환하므로, 디코딩된 결과는 원래 숫자에 가까운 부동 소수점 배열입니다.
    decrypted_result = encoder.decode(decrypted_result_encoded)
    
    print(f"동형 암호화 연산을 통한 복호화된 결과 (근사치): {decrypted_result[0]:.4f}") 
    print(f"평문 계산 결과: {model_weight_W * client_input_x + model_bias_b:.4f}")