Using SM4 Symmetric Key (CBC Mode) for Encryption and Decryption
Note:
Currently in the beta phase.
For the corresponding algorithm specifications, please refer to Symmetric Key Encryption/Decryption Algorithm Specifications: SM4.
Encryption
-
Call createSymKeyGenerator to generate a symmetric key (SymKey) with SM4 as the key algorithm and a key length of 128 bits.
For guidance on generating an SM4 symmetric key, developers can refer to the example below, combined with Symmetric Key Generation and Conversion Specifications: SM4 and Random Symmetric Key Generation. Note that there may be parameter differences between the reference documents and the current example, so please pay attention to these distinctions when reading.
-
Call createCipher with the string parameter 'SM4_128|CBC|PKCS7' to create a Cipher instance with SM4_128 as the symmetric key type, CBC as the block mode, and PKCS7 as the padding mode, which will be used to perform encryption operations.
-
Call init to set the mode to encryption (CryptoMode.EncryptMode), specify the encryption key (SymKey), and the encryption parameters (IvParamsSpec) corresponding to CBC mode, thereby initializing the encryption Cipher instance.
-
Call update to update the data (plaintext).
- For small amounts of data, you can directly call doFinal after initialization.
- For large amounts of data, you can call update multiple times, i.e., perform segmented encryption/decryption.
-
Call doFinal to obtain the encrypted data.
Since the data has already been passed via update, pass None for the data parameter here.
Decryption
-
Call createCipher with the string parameter 'SM4_128|CBC|PKCS7' to create a Cipher instance with SM4_128 as the symmetric key type, CBC as the block mode, and PKCS7 as the padding mode, which will be used to perform decryption operations.
-
Call init to set the mode to decryption (CryptoMode.DecryptMode), specify the decryption key (SymKey), and the decryption parameters (IvParamsSpec) corresponding to CBC mode, thereby initializing the decryption Cipher instance.
-
Call update to update the data (ciphertext).
-
Call doFinal to obtain the decrypted data.
Example
The synchronous method example is as follows:
import kit.CryptoArchitectureKit.*
import ohos.hilog.Hilog
import ohos.business_exception.BusinessException
func generateRandom(len: Int32) {
let rand = createRandom()
let generateRandSync = rand.generateRandom(len)
return generateRandSync
}
func genIvParamsSpec() {
let ivBlob = generateRandom(16)
let ivParamsSpec: IvParamsSpec = IvParamsSpec("IvParamsSpec", ivBlob)
return ivParamsSpec
}
let iv = genIvParamsSpec()
// Encrypt message.
func encryptMessage(symKey: SymKey, plainText: DataBlob) {
let cipher = createCipher('SM4_128|CBC|PKCS7')
cipher.initialize(CryptoMode.EncryptMode, symKey, Some(iv))
let cipherData = cipher.doFinal(plainText)
return cipherData
}
// Decrypt message.
func decryptMessage(symKey: SymKey, cipherText: DataBlob) {
let decoder = createCipher('SM4_128|CBC|PKCS7')
decoder.initialize(CryptoMode.DecryptMode, symKey, Some(iv))
// decoder.`init`(DECRYPT_MODE, symKey, iv)
let decryptData = decoder.doFinal(cipherText)
return decryptData
}
func genSymKeyByData(symKeyData: Array<UInt8>) {
let symKeyBlob: DataBlob = DataBlob(symKeyData)
let aesGenerator = createSymKeyGenerator('SM4_128')
let symKey = aesGenerator.convertKey(symKeyBlob)
Hilog.info(0, '', 'convertKey success')
return symKey
}
func test() {
try {
let keyData: Array<UInt8> = [7, 154, 52, 176, 4, 236, 150, 43, 237, 9, 145, 166, 141, 174, 224, 131]
let symKey = genSymKeyByData(keyData)
let message = "This is a test"
let plainText: DataBlob = DataBlob(message.toArray())
let encryptText = encryptMessage(symKey, plainText)
let decryptText = decryptMessage(symKey, encryptText)
if (plainText.data.toString() == decryptText.data.toString()) {
Hilog.info(0, '', 'decrypt ok')
Hilog.info(0, '', 'decrypt plainText: ' + String.fromUtf8(decryptText.data))
} else {
Hilog.error(0, '', 'decrypt failed')
}
} catch (e: BusinessException) {
Hilog.error(0, '', "SM4 ${e}, error code: ${e.code}")
}
}