一種保留格式的加密算法FPE


一、背景 

      在實際應用中,對數據庫中的信用卡號、身份證號等敏感數據進行加密是非要有必要的,然而使用傳統的分組密碼通常會擴展數據,使數據長度和類型發送變化,需要修改數據庫結構或應用程序來適應這些變化,成本非常高。為了解決這類問題,期望出現加密后的密文和加密前的明文格式一致(長度和字符類型一樣)的加密算法,也就是本文要提到的FPE(format-preserving encryption)算法。

      FPE算法的初衷是為了解決數據庫或者應用系統中敏感數據的加密問題,隨着研究的進展,其應用並不僅限於此,比如FPE可以應用於數據遮蔽(data masking)領域,通過克隆原始數據進行掩碼轉換,輸出一個與元數據格式、關聯一模一樣的數據,用於解決從生產環境的數據向測試環境(或者開發環境)導入時可能產生的數據內容、數據安全問題,此外,FPE對於網絡數據安全一樣有用,可以使數據報在不改變格式的情況下在傳輸過程中受到保護。

二、特征

1、數據不能被擴充. 例如當加密N位的數字時,必須輸出另外一個N位的數字

2、數據類型不能被改變. 例如一個只包含數字的串加密后輸出的串也只能是數字

3、數據必須能被確定性加密.例如對於數據庫中作為主鍵或者索引字段的數據,被加密后將保留其所在的列作為主鍵或者索引的特性

三、構建方法

學術界關於格式保留加密的研究已持續多年,2002年,Black和Rogaway提出了3種FPE構建方法:

1、 Prefix

2、Cycle-Walking

3、Generalized-Feistel

這三種方法成為構造FPE模型的基本方法,其中Generalized-Feistel方法的適用性更為廣泛,其核心思路是基於Feistel網絡來構建符合整數集大小的分組密碼,並結合Cycle-Walking方法使最終密文輸出在合理范圍內,Feistel網絡可以通過定義分組大小、密鑰長度、輪次數、子密鑰生成、輪函數等來構造一個分組密碼。

具體文獻:https://www.docin.com/p-132469640.html

四、實戰代碼

@UtilityClass
public class FPEncryptionUtils {

    private static final String SECRET_KEY="yoursecuritypriv";

    private static final byte[] A_TWEAK_SUFFIX ="yoursecuritypriv".getBytes();

    private static final Alphabet EXTEND_ALPHABET=new ExtendAlphabet();

    private static final TextToIntTransformer TEXT_TO_INT_TRANSFORMER = new GenericTransformations(EXTEND_ALPHABET.availableCharacters());

    private static final IntToTextTransformer INT_TO_TEXT_TRANSFORMER = new GenericTransformations(EXTEND_ALPHABET.availableCharacters());

    private static final ThreadLocal<FormatPreservingEncryption> SEED_POOL= ThreadLocal.withInitial(
            () -> FormatPreservingEncryptionBuilder
                    .ff1Implementation()
                    .withDomain(new GenericDomain(EXTEND_ALPHABET,TEXT_TO_INT_TRANSFORMER,INT_TO_TEXT_TRANSFORMER))
                    .withDefaultPseudoRandomFunction(SECRET_KEY.getBytes())
                    .withDefaultLengthRange()
                    .build());

    public static String encrypt(String plainText){
        if(StringUtils.isEmpty(plainText)){
            return null;
        }
        return SEED_POOL.get().encrypt(plainText,A_TWEAK_SUFFIX);
    }

    public static String decrypt(String cipherText){
        if(StringUtils.isEmpty(cipherText)){
            return null;
        }
        return SEED_POOL.get().decrypt(cipherText,A_TWEAK_SUFFIX);
    }

    private static class ExtendAlphabet implements Alphabet{

        private static final char[] NUM_AND_CHARACTER_CHARS = new char[] {
                '1', '2', '3', '4', '5', '6', '7', '8','9','0',
                'A','B','C','D','E','F','G','H','I','J','K','L',
                'M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'};

        private static final char[] ONLY_NUM=new char[]{
            '1', '2', '3', '4', '5', '6', '7', '8','9','0'
        };        

        @Override
        public char[] availableCharacters() {
            return NUM_AND_CHARACTER_CHARS;
        }

        @Override
        public Integer radix() {
            return NUM_AND_CHARACTER_CHARS.length;
        }
    }
}

五、效果展示

輸入:1008611           輸出:8415027
輸入:18815658640       輸出:06207345474
輸入:10086CHF11LH      輸出:ZJ8VAT6W7WRL


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM