sm4/aes_FPE ,FF3-1 保留格式加密

手把手教你用国密SM4实现FPE格式保留加密(附OpenSSL源码调试指南) 本文详细介绍了如何基于国密SM4算法实现FPE格式保留加密,包括核心概念解析、OpenSSL源码调试指南以及实战部署建议。通过FF1标准的10轮迭代过程分析,帮助开发者掌握SM4-FPE的实现细节,提升数据安全保护能力。 阅读详情
"""
Author: tanglei
DateTime:2024-11-18 完成
微信:ciss_cedar
欢迎一起学习
使用了其他人的方法封装
"""

# Package ff3 implements the FF3-1 format-preserving encryption algorithm/scheme

import math
import string

from symmetric_alg import MySymCipher, AlgName, CipherMode

# The recommendation in Draft SP 800-38G was strengthened to a requirement in Draft
# SP 800-38G Revision 1: the minimum domain size for FF1 and FF3-1 is one million.

NUM_ROUNDS = 8
BLOCK_SIZE = 16  # aes.BlockSize
TWEAK_LEN = 8  # Original FF3 tweak length
TWEAK_LEN_NEW = 7  # FF3-1 tweak length
HALF_TWEAK_LEN = TWEAK_LEN // 2


def reverse_string(txt):
    """func defined for clarity"""
    return txt[::-1]


class FF3Cipher:

    DOMAIN_MIN = 1_000_000  # 1M required in FF3-1
    BASE_STR = string.digits+ string.ascii_uppercase + string.ascii_lowercase
    Other='+/='
    BASE_STR=BASE_STR+Other
    BASE_STR_LEN = len(BASE_STR)
    RADIX_MAX = 256  # Support 8-bit alphabets for now
    # radix=10 数字, 16 16进制字符,65 base64 = 用于填充故实际上是65个字符
    def __init__(self, key,iv,mode,alg_name,tweak, radix=10):
        key_bytes = bytes.fromhex(key)
        self.key=key
        self.iv=iv
        self.mode=mode
        self.alg_name=alg_name
        self.tweak = str(tweak).ljust(16,'0')
        self.radix = radix
        if radix <= FF3Cipher.BASE_STR_LEN:
            self.alphabet = FF3Cipher.BASE_STR[0:radix]
        else:
            self.alphabet = None

        # Calculate range of supported message lengths [minLen..maxLen]
        # per revised spec, radix^minLength >= 1,000,000.
        self.minLen = math.ceil(math.log(FF3Cipher.DOMAIN_MIN) / math.log(radix))

        # We simplify the specs log[radix](2^96) to 96/log2(radix) using the log base
        # change rule
        self.maxLen = 2 * math.floor(96/math.log2(radix))

        klen = len(key_bytes)

        # Check if the key is 128, 192, or 256 bits = 16, 24, or 32 bytes
        if klen not in (16, 24, 32):
            raise ValueError(f'key length is {klen} but must be 128, 192, or 256 bits')

        # While FF3 allows radices in [2, 2^16], commonly useful range is 2..62
        if (radix < 2) or (radix > FF3Cipher.RADIX_MAX):
            raise ValueError("radix must be between 2 and 62, inclusive")

        # Make sure 2 <= minLength <= maxLength
        if (self.minLen < 2) or (self.maxLen < self.minLen):
            raise ValueError("minLen or maxLen invalid, adjust your radix")

        # AES block cipher in ECB mode with the block size derived based on the length
        # of the key. Always use the reversed key since Encrypt and Decrypt call ciph
        # expecting that

        #self.aesCipher = AES.new(reverse_string(key_bytes), AES.MODE_ECB)

    # factory method to create a FF3Cipher object with a custom alphabet
    @staticmethod
    def withCustomAlphabet(key, tweak, alphabet):
        c = FF3Cipher(key, tweak, len(alphabet))
        c.alphabet = alphabet
        return c

    def encrypt(self, plaintext):
        """Encrypts the plaintext string and returns a ciphertext of the same length
        and format"""
        return self.encrypt_with_tweak(plaintext, self.tweak)


    # EncryptWithTweak allows a parameter tweak instead of the current Cipher's tweak

    def encrypt_with_tweak(self, plaintext, tweak):

        tweakBytes = bytes.fromhex(tweak)

        n = len(plaintext)

        # Check if message length is within minLength and maxLength bounds
        if (n < self.minLen) or (n > self.maxLen):
            raise ValueError(f"message length {n} is not within min {self.minLen} and "
                             f"max {self.maxLen} bounds")

        # Make sure the given the length of tweak in bits is 56 or 64
        if len(tweakBytes) not in [TWEAK_LEN, TWEAK_LEN_NEW]:
            raise ValueError(f"tweak length {len(tweakBytes)} invalid: tweak must be 56"
                             f" or 64 bits")

        # Todo: Check message is in current radix

        # Calculate split point
        u = math.ceil(n / 2)
        v = n - u

        # Split the message
        A = plaintext[:u]
        B = plaintext[u:]

        if len(tweakBytes) == TWEAK_LEN_NEW:
            # FF3-1
            tweakBytes = calculate_tweak64_ff3_1(tweakBytes)

        Tl = tweakBytes[:HALF_TWEAK_LEN]
        Tr = tweakBytes[HALF_TWEAK_LEN:]
       # logger.debug(f"Tweak: {tweak}, tweakBytes:{tweakBytes.hex()}")

        # Pre-calculate the modulus since it's only one of 2 values,
        # depending on whether i is even or odd

        modU = self.radix ** u
        modV = self.radix ** v
       # logger.debug(f"modU: {modU} modV: {modV}")

        # Main Feistel Round, 8 times
        #
        # AES ECB requires the number of bits in the plaintext to be a multiple of
        # the block size. Thus, we pad the input to 16 bytes

        for i in range(NUM_ROUNDS):
            # logger.debug(f"-------- Round {i}")
            # Determine alternating Feistel round side
            if i % 2 == 0:
                m = u
                W = Tr
            else:
                m = v
                W = Tl

            # P is fixed-length 16 bytes
            P = calculate_p(i, self.alphabet, W, B)
            revP = reverse_string(P)

            key = bytes.fromhex(self.key)
            iv =  bytes.fromhex(self.iv)
            my_alg = MySymCipher(key, iv, self.mode, self.alg_name)
            S = my_alg.encrypt_bytes(bytes(revP))

           # S = self.aesCipher.encrypt(bytes(revP))

            S = reverse_string(S)
            # logger.debug("S:    ", S.hex())

            y = int.from_bytes(S, byteorder='big')

            # Calculate c
            c = decode_int_r(A,  self.alphabet)

            c = c + y

            if i % 2 == 0:
                c = c % modU
            else:
                c = c % modV

            # logger.debug(f"m: {m} A: {A} c: {c} y: {y}")
            C = encode_int_r(c, self.alphabet, int(m))

            # Final steps
            A = B
            B = C

            # logger.debug(f"A: {A} B: {B}")

        return A + B

    def decrypt(self, ciphertext):

        return self.decrypt_with_tweak(ciphertext, self.tweak)

    def decrypt_with_tweak(self, ciphertext, tweak):

        tweakBytes = bytes.fromhex(tweak)

        n = len(ciphertext)

        # Check if message length is within minLength and maxLength bounds
        if (n < self.minLen) or (n > self.maxLen):
            raise ValueError(f"message length {n} is not within min {self.minLen} and "
                             f"max {self.maxLen} bounds")

        # Make sure the given the length of tweak in bits is 56 or 64
        if len(tweakBytes) not in [TWEAK_LEN, TWEAK_LEN_NEW]:
            raise ValueError(f"tweak length {len(tweakBytes)} invalid: tweak must be 8 "
                             f"bytes, or 64 bits")

        # Todo: Check message is in current radix

        # Calculate split point
        u = math.ceil(n/2)
        v = n - u

        # Split the message
        A = ciphertext[:u]
        B = ciphertext[u:]

        if len(tweakBytes) == TWEAK_LEN_NEW:
            # FF3-1
            tweakBytes = calculate_tweak64_ff3_1(tweakBytes)

        Tl = tweakBytes[:HALF_TWEAK_LEN]
        Tr = tweakBytes[HALF_TWEAK_LEN:]
        #logger.debug(f"Tweak: {tweak}, tweakBytes:{tweakBytes.hex()}")

        # Pre-calculate the modulus since it's only one of 2 values,
        # depending on whether i is even or odd

        modU = self.radix ** u
        modV = self.radix ** v
        #logger.debug(f"modU: {modU} modV: {modV}")

        # Main Feistel Round, 8 times

        for i in reversed(range(NUM_ROUNDS)):

            # logger.debug(f"-------- Round {i}")
            # Determine alternating Feistel round side
            if i % 2 == 0:
                m = u
                W = Tr
            else:
                m = v
                W = Tl

            # P is fixed-length 16 bytes
            P = calculate_p(i, self.alphabet, W, A)
            revP = reverse_string(P)

           # S = self.aesCipher.encrypt(bytes(revP))
            key = bytes.fromhex(self.key)
            #alg_name = AlgName.SM4.value
            #mode = CipherMode.CBC.value
            iv = bytes.fromhex(self.iv)
            my_alg = MySymCipher(key, iv, self.mode, self.alg_name)
            S = my_alg.encrypt_bytes(bytes(revP))
            #plain = my_alg.decrypt_bytes(cipher)
            S = reverse_string(S)

            # logger.debug("S:    ", S.hex())

            y = int.from_bytes(S, byteorder='big')

            # Calculate c
            c = decode_int_r(B, self.alphabet)

            c = c - y

            if i % 2 == 0:
                c = c % modU
            else:
                c = c % modV

            # logger.debug(f"m: {m} B: {B} c: {c} y: {y}")
            C = encode_int_r(c, self.alphabet, int(m))

            # Final steps
            B = A
            A = C

            # logger.debug(f"A: {A} B: {B}")

        return A + B


def calculate_p(i, alphabet, W, B):
    # P is always 16 bytes
    P = bytearray(BLOCK_SIZE)

    P[0] = W[0]
    P[1] = W[1]
    P[2] = W[2]
    P[3] = W[3] ^ int(i)

    # The remaining 12 bytes of P are for rev(B) with padding

    BBytes = decode_int_r(B, alphabet).to_bytes(12, "big")
    # logger.debug(f"B: {B} BBytes: {BBytes.hex()}")

    P[BLOCK_SIZE - len(BBytes):] = BBytes
    return P

def calculate_tweak64_ff3_1(tweak56):
    tweak64 = bytearray(8)
    tweak64[0] = tweak56[0]
    tweak64[1] = tweak56[1]
    tweak64[2] = tweak56[2]
    tweak64[3] = (tweak56[3] & 0xF0)
    tweak64[4] = tweak56[4]
    tweak64[5] = tweak56[5]
    tweak64[6] = tweak56[6]
    tweak64[7] = ((tweak56[3] & 0x0F) << 4)
    return tweak64

def encode_int_r(n, alphabet, length=0):

    base = len(alphabet)
    if (base > FF3Cipher.RADIX_MAX):
        raise ValueError(f"Base {base} is outside range of supported radix "
                         f"2..{FF3Cipher.RADIX_MAX}")

    x = ''
    while n >= base:
        n, b = divmod(n, base)
        x += alphabet[b]
    x += alphabet[n]

    if len(x) < length:
        x = x.ljust(length, alphabet[0])

    return x


def decode_int_r(astring, alphabet):

    strlen = len(astring)
    base = len(alphabet)
    num = 0

    idx = 0
    try:
        for char in reversed(astring):
            power = (strlen - (idx + 1))
            num += alphabet.index(char) * (base ** power)
            idx += 1
    except ValueError:
        raise ValueError(f'char {char} not found in alphabet {alphabet}')

    return num

# def encrypt_idcard(key, iv, mode, alg_name, tweak, idcard,radix=10):
#     #alg_name = AlgName.SM4.value
#     #mode = CipherMode.CBC.value
#     temp_source=''
#     if radix == 10 and len(idcard) == 18:
#         if idcard[-1:] in ('X','x'):
#             temp_source = idcard[:17]+'2'
#         else:
#             temp_source=idcard
#         myFF3Cipher = FF3Cipher(key, iv, mode, alg_name, tweak, radix=radix)
#         result_value = myFF3Cipher.encrypt(temp_source)
#         return result_value
#     else:
#             return 'not id_card'
#
# def decrypt_idcard(key, iv, mode, alg_name, tweak, enc_idcard,radix=10,):
#         if radix == 10 and len(enc_idcard) == 18:
#             myFF3Cipher = FF3Cipher(key, iv, mode, alg_name, tweak, radix=radix)
#             result_value = myFF3Cipher.decrypt(enc_idcard)
#             if result_value[-1:]=='2':
#                 result_value=result_value[0:17]+'X'
#             return result_value
#         else:
#             return 'not id_card'

def main():
    # 示例用法


    key = '2934412A66B7A186DC35DC40E926F9EE'
    iv = '86CD720D75F4622DBE96078A3CD1076E'
    # key = bytes.fromhex(key)
    # iv = bytes.fromhex(iv)
    tweak = '86CD720D75F4622D'

    radix = 65  # 基数
    plaintext = '12345678X/'

    alg_name = AlgName.SM4.value
    mode = CipherMode.CBC.value
    myFF3Cipher = FF3Cipher(key, iv, mode, alg_name, tweak, radix=radix)
    ciphertext = myFF3Cipher.encrypt(plaintext)
    print("plaintext:", plaintext)
    print("Ciphertext:", ciphertext)
    decrypted = myFF3Cipher.decrypt(ciphertext)
    print("Decrypted:", decrypted)
    print('-'*66)
    id_card = '10110219791119002X'
    radix=10
    if radix == 10 and len(id_card) == 18:
        if id_card[-1:] in ('X','x'):
                plaintext = id_card[:17]+'2'
    myFF3Cipher = FF3Cipher(key, iv, mode, alg_name, tweak, radix=radix)
    enc_id_card = myFF3Cipher.encrypt(plaintext)

    dec_id_card=myFF3Cipher.decrypt(enc_id_card)
    if dec_id_card[-1:]=='2':
        dec_id_card=dec_id_card[0:17]+'X'
    print(f'id_card={id_card}')
    print(f'enc_id_card={enc_id_card}')
    print(f'dec_id_card={dec_id_card}')

if __name__ == "__main__":
    main()
国密SM4实现格式保留加密(FPE):原理、C语言实战与调试指南 格式保留加密是一种特殊的加密技术,它确保加密后的数据与原始数据保持相同的格式和长度,例如加密后的身份证号依然是15位数字。其核心原理通常基于经典的Feistel网络结构,通过多轮迭代和模运算,将数据始终约束在目标字符集范围内。这种技术在数据脱敏、隐私保护场景中极具价值,尤其适用于金融、电信等对数据格式有严格校验的行业系统。本文以国密SM4算法构建安全的伪随机轮函数,详细解析了FPE的算法设计,并提供了可编译运行的C语言实现代码,帮助开发者跨越从理论到工程实践的鸿沟,解决数据加密中的格式约束难题。 阅读详情

相关推荐

手把手教你用国密SM4实现FPE格式保留加密(附完整C代码与调试过程)

本文详细介绍了如何使用国密SM4算法实现FPE格式保留加密技术,包括核心原理、FF1算法解析、SM4适配改造及完整C代码实现。通过实战案例和调试技巧,帮助开发者掌握在金融、医疗等领域保护敏感数据的同时保持原始格式的关键技术,满足合规要求并提升系统兼容性。

weixin_30530339的博客 285

基于SM4的FPE算法测试

基于SM4的FPE保留格式加密

viqjeee的博客 2872

国密SM4与FF1算法融合:FPE在数据脱敏中的实战测试

本文探讨了国密SM4与FF1算法融合在数据脱敏中的实战应用,详细解析了SM4替换AES的技术难点与解决方案。通过实战测试验证了该方案在金融数据脱敏中的高效性与合规性,为金融级应用提供了关键优化建议。

weixin_30323631的博客 144

bzoj 1941 Hide and Seek —— K-D树

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1941 曼哈顿最小距离估价:max( 0, t[x].mn[i] - v.p[i] ) + max( 0, v.p[i] - t[x].mx[i] ),可理解为到边界; 曼哈顿最大距离估价:max( abs( t[x].mn[i] - v.p[i] ) + abs( t[x].m...

aodan5477的博客 133

国密SM4算法实现格式保留加密:原理、OpenSSL调试与工程实践

格式保留加密是一种特殊的加密技术,其核心在于加密后的密文格式与原始明文保持一致,这在数据脱敏、数据库加密等场景中至关重要。其原理通常基于Feistel网络结构,通过多轮迭代和模运算将加密过程约束在特定字符集内,从而在不改变数据格式的前提下保障信息安全。该技术的核心价值在于能无缝兼容现有业务系统,无需修改数据库结构或业务逻辑。在金融、政务等对数据安全与合规性要求极高的领域,结合我国商用密码标准SM4算法实现格式保留加密,成为满足安全与格式双重要求的优选方案。本文通过OpenSSL源码级调试,深入解析了SM4在

leonard61306500的专栏 448

手把手调试:一步步拆解SM4-FF1算法加密流程(附详细内存数据变化)

本文深入解析SM4-FF1算法的加密流程,从原理到内存级调试实战,详细拆解了格式保留加密(FPE)的核心概念和SM4与FF1的结合优势。通过实际代码示例和内存数据变化分析,帮助开发者掌握算法实现细节,提升调试和优化能力,适用于金融和数据安全领域。

weixin_30905133的博客 171

数据脱敏新选择:用SM4-FPE保护你的手机号和身份证号(实战对比传统掩码)

本文深入探讨了SM4-FPE技术在数据脱敏中的应用,对比传统掩码方法,展示了其在安全性、业务兼容性和合规性方面的优势。通过实战代码示例和性能优化建议,帮助开发者高效实现手机号和身份证号的格式保留加密,满足金融、医疗等行业的数据保护需求。

weixin_27722377的博客 461

用国密SM4实现FPE格式保留加密:一个保护手机号、银行卡号的Python实战案例

本文详细介绍了如何使用国密SM4算法结合FF1格式保留加密(FPE)技术保护手机号、银行卡号等敏感数据。通过Python实战案例,展示了SM4-FF1的实现过程、性能优化建议及生产环境部署方案,帮助开发者在满足国产密码合规要求的同时,确保数据安全性与业务兼容性。

weixin_42530732的博客 193

分组密码算法的工作模式

因为当前的SM4算法的软件实现优化主要是通过SIMD指令并行处理多个分组来达到速度提升的,而这一优化策略无法应用于CBC模式当中,目前即使是优化过的SM4软件实现,在大多数计算环境中CBC模式下能够处理的数据量不超过100MB,而CTR模式等可以兼容分组并行处理的工作模式,则甚至可以达到600MB/s以上的处理速度(单线程下),因此SM4-CCM模式中,CBC-MAC的计算会成为整个算法甚至整个业务场景的性能瓶颈。综上,笔者推荐在CBC,CFB,OFB以及CTR模式中,优先选用CTR模式。

共勉 1717

【信息科学与工程学】【安全领域】第三十五篇 网络安全算法表

编号算法名称算法的逐步骤思考推理的数学方程式和分解的数学方程式参数/变量列表复杂度(时间/空间)1​AES (高级加密标准)​1. 密钥扩展:从初始密钥生成轮密钥。 2. 初始轮: 3. 主轮循环(Nr-1轮):  - SubBytes:(非线性字节替换)  - ShiftRows:对状态矩阵的行进行循环移位。  - MixColumns:(在GF(2⁸)上的矩阵乘法)  - AddRoundKey: 4. 最终轮:执行SubBytes、ShiftRows、AddR

weixin_49199313的博客 1379

python-fpe:FPE-在Python中使用FF3进行格式保留加密

ff3-Python中的格式保留加密 NIST认可的Python格式保留加密(FPE)FF3算法的实现。 此软件包遵循FF3格式保存加密算法,如2016年3月NIST出版物《格式保存加密方法》中所述,并于2020年2月28日进行了修订,其中包括FF3-1的更新草案。 此软件包中已部分实现了对最小域大小的更改和调整后的调整长度的更新,其中包括对域大小的更新。 预计最终标准将提供将调整长度更改为56位所需的新测试向量。 当前,调整保持设置为64位。 需要 该项目是使用Python 3.6及更高版本构建和测试的。 它需要pycryptodome库: pip3 install pycryptodome 安装 使用pip安装此项目: pip3 install ff3 用法 FF3是Feistel密码,并且Feistel密码使用代表字母的基数初始化。 python中的实用小数限制为36表示

国密不是“换个算法“:SM2/3/4 与 GM/T 0051 怎么撑起密评合规

很多团队把"国密改造"理解成"把 AES 换成 SM4",结果密评还是过不了。本文从国密算法的实际谱系(SM2 非对称、SM3 哈希、SM4 对称、FPE 格式保留)讲到合规抓手 GM/T 0051,说明国密改造为什么是"算法+密钥管理+合规认证"的系统性工程,而不是单点替换。

m0_75002133的博客 201

xilinx zynq-7000 linux下rs422串口通信测试步骤

这几天使用xilinx的zynq-7000系列调试rs422串口,期间遇到不少问题,好在最终调试完成,在这里记录一下调试步骤。 我用的soc型号是xc7z100,板载了2个rs422外设,PS端有2个uart控制器,uart0用于连接rs232并作为console控制台输出,uart1连接rs422。 rs422和主板连线原理图如下: 其中422_TXD1_3V3 和422_RXD1_3V3 为数据发送和接收引脚,422_TXD_DE1_3V3为发送使能引脚,422_RXD_REn1_...

dongyunke的博客 5907

数据库安全网关体系中,对Long、Date类型列加密的方法

数据库安全网关中Long和Date类型加密面临安全性需求与业务查询需求的平衡问题。传统加密会破坏数据类型特性,导致查询功能丧失。本文解析了三种加密方案:确定性加密(支持等值查询但安全性低)、随机性加密(安全性高但无法查询)、格式保留加密(FPE)。FPE能保持数据原始格式,允许等值查询和部分范围查询,但实现复杂。对于Long值可直接加密为二进制,Date值可转换为Epoch Millis再加密。FPE通过有限域映射原理,在保证安全性的同时维持数据格式不变,是解决这一矛盾的有效方案。

风杨 998

AI赋能软件测试:从冒烟测试到全流程智能化的效率革命

软件测试是确保软件质量的关键环节,其核心原理是通过预设用例验证系统功能是否符合预期。传统测试方法依赖人工编写和维护脚本,面临维护成本高、适应性差等挑战。随着人工智能技术的发展,特别是自然语言处理和计算机视觉的成熟,AI为测试领域带来了新的技术价值。通过让AI理解应用界面和业务逻辑,可以实现测试用例的智能生成、自主执行和结果分析,显著提升测试效率和覆盖率。在实际应用场景中,AI驱动的冒烟测试能够动态适应UI变化,自动分析失败日志,将测试人员从重复劳动中解放出来,专注于更复杂的质量策略设计。本文基于AI在冒烟测

weixin_28841265的博客 306

Logisim实战:手把手教你设计硬布线版MIPS CPU(多周期/8指令/附电路图)

本文是一份详细的Logisim实战指南,手把手教你设计一个采用硬布线控制的多周期MIPS CPU。文章深入剖析了硬布线控制与微程序控制的核心理念差异,并逐步讲解了从定义执行状态、构建状态跳转逻辑到生成控制信号、集成测试的完整流程,最终实现一个支持8条指令、可运行简单程序的处理器模型。

g9h0i1的博客 592

数据库字段加密后模糊查询不可用?DBG保留格式加密+可搜索加密实战

最近某金融科技公司的DBA老张遇到了一个棘手的问题:合规部门要求:用户手机号、身份证号必须在数据库中加密存储,明文绝对不能出现。业务部门要求:客服系统需要按手机号后4位模糊搜索用户,查询响应必须在200ms内。老张的第一反应是"这不矛盾吗"——字段加密后,密文是乱码,这种查询根本跑不了,必须全表解密再匹配,性能完全不可接受。这不是个案。数据合规(等保、GDPR、个人信息保护法)要求敏感数据加密,而业务部门要求加密后的数据仍然可查、可用、可统计——两个需求天然冲突。

安当加密 400

【Pico手势开发实战】基于SteamVR串流与MRTK3的跨平台交互方案

本文详细介绍了在Pico设备上,结合SteamVR串流与微软MRTK3框架,实现高效跨平台手势交互开发的完整方案。该方案通过在PC端运行Unity项目并串流至头显,利用MRTK3封装的手势识别与交互组件,大幅提升了开发调试效率与性能上限,并确保了未来向其他OpenXR设备的良好兼容性。

weixin_29001683的博客 217

【系统安全】信息脱敏存储:场景、需求与实现方案详解

场景上:金融、医疗、政务等强监管行业是"硬要求",其他行业是"等保/个保法合规 + 防拖库/防内鬼"的普遍诉求;且脱敏要求贯穿存储、展示、日志、测试、共享全链路,不止存储一环。需求上:核心是字段级分级分类 + 加密/脱敏算法合规 + 密钥管理 + 审计;同时往往伴随**精确查询(登录、核验)与模糊查询(运营/客服/风控)**的业务需求。模糊查询:可以共存,但必须提前设计。工程主流组合是盲索引(等值)+ 分段明文索引(尾号/姓氏)+ 脱敏副本(展示/粗查)+ ES 脱敏索引(任意分词)

weixin_44823875的博客 469

SOLIDWORKS Flow Simulation 颗粒分离器仿真:从流场分析到分离效率优化

计算流体力学(CFD)是研究流体流动、传热及相关物理现象的核心工具,其基本原理是通过数值方法求解控制流体运动的纳维-斯托克斯方程。在工程实践中,CFD的价值在于能够对复杂流动进行高保真度仿真,从而在产品设计阶段预测性能、优化结构,显著降低物理样机的试制成本和周期。颗粒分离器作为环保、化工、矿业等领域的关键设备,其设计核心在于平衡分离效率与压力损失。借助SOLIDWORKS内嵌的Flow Simulation模块,工程师可以高效地执行流体仿真,特别是对涉及离散相的颗粒运动进行轨迹追踪和效率统计。该技术方案通过

weixin_28709649的博客 325

跨境TRS投资操作指南与系统解决方案

3 点击【申请 TRS 账户】,查看风险披露,录入账户参数、确定录入的参数信息,进行身份验证,输入验证码,TRS 账户开户申请已提交,后台对已提交的 TRS 开户申请进行审核,审核成功后,短信邮箱提醒,进行登录;2.点击【申请TRS账户】,查看风险披露,录入账户参数、确定录入的参数信息,进行身份验证,输入验证码,TRS账户开户申请已提交,后台对已提交的TRS开户申请进行审核,审核成功后,短信邮箱提醒,进行登录;4)更广泛的投资选择:相比A股通,TRS可以交易更多的A股标的,提供了更广泛的投资选择。

2401_85487119的博客 2853

ECU被篡改、App被逆向、算法被偷——车载系统三重安全危机与破解方案

从ECU固件篡改到IVI车机App逆向再到ADAS算法盗窃,智能汽车面临的三重安全危机,每一重都可能让车企付出千万级代价。本文逐一拆解三个痛点的攻击路径和技术根源,给出从三级密钥体系、应用层加固到推理态加密的分层破解方案,含6维度防护对比表和10周落地路线。

安当加密官方技术博客 | 数据库加密与等保合规实战指南 1149

黑猫带你学eMMC协议第1篇:全网最全emmc协议中文详讲,这份学习框架图,你值得拥有!!!(持续更新中...)

黑猫带你学eMMC协议第7篇:全网最全emmc写保护详解(write protect) 黑猫带你学eMMC协议第8篇:emmc可靠写详解(Write Reliability) 黑猫带你学eMMC协议第9篇:emmc的分区配置(partitioning) 黑猫带你学eMMC协议第10篇:eMMC命令队列详解(CMDQ) 黑猫带你学eMMC协议第11篇:eMMC擦除详解(erase/trim/discard/sanitize/secure erase/secure trim…) 黑猫带你学eMMC协议第12篇:

黑猫奥利奥的博客 2万+

交通运输数据安全管理办法合规解读密评与关键基础设施保护

2025年交通运输行业数据安全管理办法深度解读,含密评十大检查项逐条对应、六子行业保护重点、CII关键设施判定标准和12个月四步整改时间表。

安当加密官方技术博客 | 数据库加密与等保合规实战指南 273

电容放电测试解析

电子设备断电后滤波电容残留电荷存在触电风险,需符合IEC等安全标准对放电时间的要求。放电测试需测量电容电压下降至安全值的时间,设计可采用主动放电电路或被动放电电阻。常见问题包括电阻选择不当或电路设计缺陷,建议预留放电时间裕度并采用组合放电方案。合规的放电设计是确保产品安全性和可靠性的关键环节。

硬核科技 803

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

金融科技开源实践:麟宇APP风控与数据安全架构解析

规则引擎作为现代金融系统的核心组件,通过预定义业务规则实现实时风险决策。Drools等开源规则引擎采用RETE/PHREAK算法,将规则编译为可执行网络,在金融风控场景中实现毫秒级响应。结合机器学习特征服务,可构建双轨风控体系,既保障业务灵活性又具备智能决策能力。数据安全方面,格式保留加密(FPE)技术在保持数据格式的同时实现加密,特别适合金融账号等结构化数据的脱敏处理。这些技术在移动金融、支付清算等场景有广泛应用,麟宇APP开源项目提供了经过生产验证的实现方案,其改良版gRPC通信协议和分层安全架构对金融

weixin_42525738的博客 125

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

上一篇: python对数字证书的解析
下一篇: python 的sm2的封装,包括数字信封等
CissSimkey
博客等级 码龄8年 312粉丝 42原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值