Module: GmSSL::SM4

Extended by:
FFI::Library, Helper
Defined in:
lib/gmssl/sm4.rb

Defined Under Namespace

Classes: SM4_CBC_CTX, SM4_CTR_CTX, SM4_GCM_CTX, SM4_KEY

Constant Summary collapse

SM4_KEY_SIZE =
16
SM4_BLOCK_SIZE =
16
SM4_NUM_ROUNDS =
32
SM4_GCM_MAX_TAG_SIZE =
16

Class Method Summary collapse

Methods included from Helper

bytes_to_hex_string, hex_string_to_packed_bytes

Class Method Details

.cbc_decrypt(key, iv, ciphertext) ⇒ Object



98
99
100
101
102
103
104
105
106
107
108
109
# File 'lib/gmssl/sm4.rb', line 98

def self.cbc_decrypt(key, iv, ciphertext)
  ciphertext = hex_string_to_packed_bytes ciphertext
  ctx = SM4::SM4_CBC_CTX.new
  SM4.sm4_cbc_decrypt_init(ctx, key, iv)
  decrypted = FFI::MemoryPointer.new(:uint8, ciphertext.bytesize + SM4::SM4_BLOCK_SIZE)
  outlen = FFI::MemoryPointer.new(:size_t)
  SM4.sm4_cbc_decrypt_update(ctx, ciphertext, ciphertext.bytesize, decrypted, outlen)
  decrypted_len = outlen.read(:size_t)
  SM4.sm4_cbc_decrypt_finish(ctx, decrypted + decrypted_len, outlen)
  decrypted_len += outlen.read(:size_t)
  decrypted.read_bytes(decrypted_len)
end

.cbc_encrypt(key, iv, plaintext) ⇒ Object



86
87
88
89
90
91
92
93
94
95
96
# File 'lib/gmssl/sm4.rb', line 86

def self.cbc_encrypt(key, iv, plaintext)
  ctx = SM4::SM4_CBC_CTX.new
  SM4.sm4_cbc_encrypt_init(ctx, key, iv)
  ciphertext = FFI::MemoryPointer.new(:uint8, plaintext.bytesize + SM4::SM4_BLOCK_SIZE)
  outlen = FFI::MemoryPointer.new(:size_t)
  SM4.sm4_cbc_encrypt_update(ctx, plaintext, plaintext.bytesize, ciphertext, outlen)
  ciphertext_len = outlen.read(:size_t)
  SM4.sm4_cbc_encrypt_finish(ctx, ciphertext + ciphertext_len, outlen)
  ciphertext_len += outlen.read(:size_t)
  bytes_to_hex_string ciphertext.read_bytes(ciphertext_len)
end

.ctr_encrypt(input_string, key_hex, ctr_hex) ⇒ Object



111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
# File 'lib/gmssl/sm4.rb', line 111

def self.ctr_encrypt(input_string, key_hex, ctr_hex)
  key = hex_string_to_packed_bytes(key_hex)
  ctr = hex_string_to_packed_bytes(ctr_hex)
  input_data = input_string.bytes.pack("C*")
  output_data = FFI::MemoryPointer.new(:uint8, input_data.bytesize)
  output_length = FFI::MemoryPointer.new(:size_t)
  key_ptr = FFI::MemoryPointer.new(:uint8, SM4::SM4_KEY_SIZE)
  ctr_ptr = FFI::MemoryPointer.new(:uint8, SM4::SM4_BLOCK_SIZE)
  key_ptr.put_array_of_uint8(0, key.bytes)
  ctr_ptr.put_array_of_uint8(0, ctr.bytes)
  ctx = SM4::SM4_CTR_CTX.new
  SM4.sm4_ctr_encrypt_init(ctx, key_ptr, ctr_ptr)
  SM4.sm4_ctr_encrypt_update(ctx, input_data, input_data.bytesize, output_data, output_length)
  SM4.sm4_ctr_encrypt_finish(ctx, output_data, output_length)
  encrypted_data = output_data.read_string(output_length.read(:size_t))
  encrypted_data.unpack("H*")[0]
end

.gcm_decrypt(key, iv, aad, encrypted_output, tag) ⇒ Object



150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
# File 'lib/gmssl/sm4.rb', line 150

def self.gcm_decrypt(key, iv, aad, encrypted_output, tag)
  encrypted_output = hex_string_to_packed_bytes encrypted_output
  tag = hex_string_to_packed_bytes tag
  key = hex_string_to_packed_bytes key
  iv = hex_string_to_packed_bytes iv
  key_struct = SM4::SM4_KEY.new
  key_ptr = FFI::MemoryPointer.new(:uint8, SM4::SM4_KEY_SIZE)
  key_ptr.put_array_of_uint8(0, key.bytes)
  SM4::sm4_set_encrypt_key(key_struct, key_ptr)
  iv_ptr = FFI::MemoryPointer.new(:uint8, SM4::SM4_BLOCK_SIZE)
  iv_ptr.put_array_of_uint8(0, iv.bytes)
  aad_ptr = FFI::MemoryPointer.new(:uint8, aad.bytesize)
  aad_ptr.put_array_of_uint8(0, aad.bytes)
  encrypted_ptr = FFI::MemoryPointer.new(:uint8, encrypted_output.bytesize)
  encrypted_ptr.put_array_of_uint8(0, encrypted_output.bytes)
  tag_ptr = FFI::MemoryPointer.new(:uint8, SM4::SM4_GCM_MAX_TAG_SIZE)
  tag_ptr.put_array_of_uint8(0, tag.bytes)
  decrypted_output_ptr = FFI::MemoryPointer.new(:uint8, encrypted_output.bytesize)
  SM4::sm4_gcm_decrypt(key_struct, iv_ptr, iv.bytesize, aad_ptr, aad.bytesize, encrypted_ptr, encrypted_output.bytesize, tag_ptr, SM4::SM4_GCM_MAX_TAG_SIZE, decrypted_output_ptr)
  decrypted_output = decrypted_output_ptr.read_string(encrypted_output.bytesize)
  return decrypted_output
end

.gcm_encrypt(key, iv, aad, input) ⇒ Object



129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
# File 'lib/gmssl/sm4.rb', line 129

def self.gcm_encrypt(key, iv, aad, input)
  key = hex_string_to_packed_bytes key
  iv = hex_string_to_packed_bytes iv
  key_struct = SM4::SM4_KEY.new
  key_ptr = FFI::MemoryPointer.new(:uint8, SM4::SM4_KEY_SIZE)
  key_ptr.put_array_of_uint8(0, key.bytes)
  SM4::sm4_set_encrypt_key(key_struct, key_ptr)
  iv_ptr = FFI::MemoryPointer.new(:uint8, SM4::SM4_BLOCK_SIZE)
  iv_ptr.put_array_of_uint8(0, iv.bytes)
  aad_ptr = FFI::MemoryPointer.new(:uint8, aad.bytesize)
  aad_ptr.put_array_of_uint8(0, aad.bytes)
  input_ptr = FFI::MemoryPointer.new(:uint8, input.bytesize)
  input_ptr.put_array_of_uint8(0, input.bytes)
  output_ptr = FFI::MemoryPointer.new(:uint8, input.bytesize)
  tag_ptr = FFI::MemoryPointer.new(:uint8, SM4::SM4_GCM_MAX_TAG_SIZE)
  SM4::sm4_gcm_encrypt(key_struct, iv_ptr, iv.bytesize, aad_ptr, aad.bytesize, input_ptr, input.bytesize, output_ptr, SM4::SM4_GCM_MAX_TAG_SIZE, tag_ptr)
  encrypted_output = encrypted_output = output_ptr.read_string(input.bytesize).unpack1("H*")
  tag = tag_ptr.read_string(SM4::SM4_GCM_MAX_TAG_SIZE).unpack1("H*")
  return encrypted_output, tag
end