Class: PqcRails::EnvelopeCipher

Inherits:
Object
  • Object
show all
Includes:
LengthValidation
Defined in:
lib/pqc_rails/envelope_cipher.rb

Overview

AES-256-GCMによるエンベロープ暗号化。HybridKem等で導出した32バイトの共有鍵を使って 実際のデータ(平文)を暗号化/復号する。「鍵交換」と「データ暗号化」を分離するのは、 後でActiveRecord::Encryption統合(Phase 3)で「鍵→暗号化結果」のインターフェースとして そのまま使えるようにするため。

暗号文のフォーマット: IV(12byte) + 認証タグ(16byte) + 暗号文本体 この3つを1本のバイト列にまとめて返すことで、DBカラム等に1カラムでそのまま保存できる。

使い方:

cipher = PqcRails::EnvelopeCipher.new(key) # 32バイトの鍵
encrypted = cipher.encrypt("secret")
cipher.decrypt(encrypted) # => "secret"

Constant Summary collapse

CIPHER_NAME =
"aes-256-gcm"
KEY_LENGTH =
32
IV_LENGTH =
12
TAG_LENGTH =
16

Instance Method Summary collapse

Constructor Details

#initialize(key) ⇒ EnvelopeCipher

Returns a new instance of EnvelopeCipher.



27
28
29
30
# File 'lib/pqc_rails/envelope_cipher.rb', line 27

def initialize(key)
  validate_length!(key, KEY_LENGTH, "key")
  @key = key
end

Instance Method Details

#decrypt(encrypted, associated_data: nil) ⇒ Object



44
45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/pqc_rails/envelope_cipher.rb', line 44

def decrypt(encrypted, associated_data: nil)
  iv         = encrypted[0, IV_LENGTH]
  tag        = encrypted[IV_LENGTH, TAG_LENGTH]
  ciphertext = encrypted[(IV_LENGTH + TAG_LENGTH)..]

  cipher = OpenSSL::Cipher.new(CIPHER_NAME)
  cipher.decrypt
  cipher.key = @key
  cipher.iv = iv
  cipher.auth_tag = tag
  cipher.auth_data = associated_data if associated_data

  cipher.update(ciphertext) + cipher.final
end

#encrypt(plaintext, associated_data: nil) ⇒ Object



32
33
34
35
36
37
38
39
40
41
42
# File 'lib/pqc_rails/envelope_cipher.rb', line 32

def encrypt(plaintext, associated_data: nil)
  cipher = OpenSSL::Cipher.new(CIPHER_NAME)
  cipher.encrypt
  cipher.key = @key
  iv = cipher.random_iv
  cipher.auth_data = associated_data if associated_data

  ciphertext = cipher.update(plaintext) + cipher.final

  iv + cipher.auth_tag + ciphertext
end