Class: OpenC3::EncryptionProtocol

Inherits:
Protocol
  • Object
show all
Defined in:
lib/encryption_protocol.rb

Instance Method Summary collapse

Constructor Details

#initialize(key, allow_empty_data = nil) ⇒ EncryptionProtocol

Returns a new instance of EncryptionProtocol.

Parameters:

  • key (String)

    Hex-encoded 32-byte encryption key (64 hex chars)

  • allow_empty_data (true/false/nil) (defaults to: nil)

    See Protocol#initialize



21
22
23
24
25
26
27
28
29
# File 'lib/encryption_protocol.rb', line 21

def initialize(key, allow_empty_data = nil)
  super(allow_empty_data)
  # Convert hex string to binary key
  @key = [key].pack('H*')
  raise "Key must be 32 bytes (64 hex characters)" unless @key.length == 32
  # Create cipher instances once and reuse them
  @cipher = OpenSSL::Cipher.new('aes-256-gcm')
  @decipher = OpenSSL::Cipher.new('aes-256-gcm')
end

Instance Method Details

#read_data(data, extra = nil) ⇒ Object



31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/encryption_protocol.rb', line 31

def read_data(data, extra = nil)
  return super(data, extra) if data.empty?

  begin
    @decipher.reset
    @decipher.decrypt
    @decipher.key = @key

    # Extract IV and auth tag from the data
    # Format: [12-byte IV][16-byte auth tag][ciphertext]
    iv = data[0..11]
    auth_tag = data[12..27]
    ciphertext = data[28..-1]

    @decipher.iv = iv
    @decipher.auth_tag = auth_tag

    plaintext = @decipher.update(ciphertext) + @decipher.final
    return plaintext, extra
  rescue OpenSSL::Cipher::CipherError => e
    Logger.error("EncryptionProtocol: Decryption failed: #{e.message}")
    return :DISCONNECT
  end
end

#write_data(data, extra = nil) ⇒ Object



56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/encryption_protocol.rb', line 56

def write_data(data, extra = nil)
  return super(data, extra) if data.empty?

  @cipher.reset
  @cipher.encrypt
  @cipher.key = @key

  # Generate a random IV for each message (recommended for GCM)
  iv = @cipher.random_iv
  @cipher.iv = iv

  ciphertext = @cipher.update(data) + @cipher.final
  auth_tag = @cipher.auth_tag

  # Prepend IV and auth tag to ciphertext
  # Format: [12-byte IV][16-byte auth tag][ciphertext]
  encrypted_data = iv + auth_tag + ciphertext
  return encrypted_data, extra
end