Golang FPE 使用示例

发布时间: 更新时间: 总字数:1520 阅读时间:4m 作者: IP上海 分享 网址

在 Go 语言中实现 FPE(Format-Preserving Encryption,格式保留加密)通常会遵循 NIST 发布的 FF1 或 FF3-1 算法。这些算法允许你在加密数据后,密文仍然保持与原文相同的格式和长度,这对于处理敏感数据(如信用卡号、社会安全号等)在不改变现有系统数据结构的情况下进行加密非常有用。

示例

以下是一个使用 Go 语言 FPE 开源库的示例,以 capitalone/fpe 库为例,它实现了 NIST 批准的 FF1 和 FF3 算法:

package main

import (
	"encoding/hex"
	"fmt"
	"github.com/capitalone/fpe/ff1" // 或者使用 "github.com/capitalone/fpe/ff3"
)

func main() {
	// 密钥和 Tweak 应该作为字节数组。
	// 在实际应用中,请确保你的密钥是安全生成的,并妥善管理。
	// Tweak 类似于 IV,通常不需要保密,但每次加密相同明文时应使用不同的 Tweak。
	key, err := hex.DecodeString("EF4359D8D580AA4F7F036D6F04FC6A94") // 128-bit key (16 bytes)
	if err != nil {
		panic(err)
	}

	tweak, err := hex.DecodeString("D8E7920AFA330A73") // 64-bit tweak (8 bytes)
	if err != nil {
		panic(err)
	}

	// 创建一个新的 FF1 加密器对象
	// 参数:
	// 1. radix (基数): 定义了明文和密文的字符集。例如,10 表示数字 0-9。
	// 2. maxTweakLen: Tweak 的最大长度。
	// 3. key: 加密密钥。
	// 4. tweak: 加密 Tweak。
	ff1Cipher, err := ff1.NewCipher(10, 8, key, tweak) // 对于数字字符串,radix 为 10
	if err != nil {
		panic(err)
	}

	original := "1234567890123456" // 示例:16位数字字符串 (例如信用卡号)

	// 加密
	ciphertext, err := ff1Cipher.Encrypt(original)
	if err != nil {
		panic(err)
	}

	// 解密
	plaintext, err := ff1Cipher.Decrypt(ciphertext)
	if err != nil {
		panic(err)
	}

	fmt.Println("Original:", original)
	fmt.Println("Ciphertext:", ciphertext)
	fmt.Println("Plaintext:", plaintext)

	// 示例:使用不同的 Tweak 加密相同明文
	// 在 FPE 中,Tweak 用于确保相同明文在不同上下文或每次加密时产生不同的密文。
	// 假设我们有另一个 Tweak
	anotherTweak, err := hex.DecodeString("1234567890ABCDEF")
	if err != nil {
		panic(err)
	}

	ciphertext2, err := ff1Cipher.EncryptWithTweak(original, anotherTweak)
	if err != nil {
		panic(err)
	}
	fmt.Println("\nOriginal (with another tweak):", original)
	fmt.Println("Ciphertext (with another tweak):", ciphertext2)

	plaintext2, err := ff1Cipher.DecryptWithTweak(ciphertext2, anotherTweak)
	if err != nil {
		panic(err)
	}
	fmt.Println("Plaintext (with another tweak):", plaintext2)


	// 如果需要处理包含字母的字符串,可以调整 radix
	// 例如,radix 36 包含 0-9 和 a-z
	ff1AlphaNumericCipher, err := ff1.NewCipher(36, 8, key, tweak)
	if err != nil {
		panic(err)
	}
	alphaNumericOriginal := "abc123xyz"
	alphaNumericCiphertext, err := ff1AlphaNumericCipher.Encrypt(alphaNumericOriginal)
	if err != nil {
		panic(err)
	}
	alphaNumericPlaintext, err := ff1AlphaNumericCipher.Decrypt(alphaNumericCiphertext)
	if err != nil {
		panic(err)
	}
	fmt.Println("\nOriginal (alphanumeric):", alphaNumericOriginal)
	fmt.Println("Ciphertext (alphanumeric):", alphaNumericCiphertext)
	fmt.Println("Plaintext (alphanumeric):", alphaNumericPlaintext)
}

如何运行这个示例:

  1. 安装 Go 环境: 确保你的机器上安装了 Go 语言环境。
  2. 创建项目:
    mkdir go-fpe-example
    cd go-fpe-example
    go mod init go-fpe-example
    
  3. 安装 FPE 库:
    go get github.com/capitalone/fpe
    
  4. 保存代码: 将上述 Go 代码保存为 main.go 文件。
  5. 运行:
    go run main.go
    

代码说明:

  • github.com/capitalone/fpe/ff1: 这是 Go 语言中一个流行的 FPE 实现,支持 NIST FF1 算法。该库也提供了 FF3-1 算法 (github.com/capitalone/fpe/ff3),但在某些情况下 FF3-1 已被 NIST 建议弃用,因此通常更推荐使用 FF1。
  • 密钥 (key) 和 Tweak (tweak):
    • 密钥是加密操作的核心,必须保密。示例中使用了 128 位(16 字节)的密钥。
    • Tweak(或称作上下文)是 FPE 中的一个重要参数,它允许你对相同的明文产生不同的密文。例如,在加密信用卡号时,可以把用户的 ID 或者交易 ID 作为 Tweak,这样即使是相同的卡号,在不同的交易中也会生成不同的密文。Tweak 通常不需要保密,但每次加密时需要使用。
  • NewCipher(radix, maxTweakLen, key, tweak):
    • radix (基数): 这是 FPE 的关键概念,它定义了你加密的字符集。
      • 10 用于仅包含数字的字符串(如信用卡号、电话号码)。
      • 36 用于包含数字和小写字母的字符串(0-9, a-z)。
      • 62 用于包含数字、大写字母和小写字母的字符串(0-9, a-z, A-Z)。
      • 如果你需要加密包含特殊字符的字符串,可能需要自定义一个更大的 radix 或在加密前进行字符映射。
    • maxTweakLen: Tweak 的最大允许长度。
  • Encrypt(original string)Decrypt(ciphertext string): 用于对字符串进行加密和解密。
  • EncryptWithTweak(X string, tweak []byte)DecryptWithTweak(X string, tweak []byte): 这些方法允许你在每次加密/解密时指定 Tweak,这对于重复使用同一个 ff1.Cipher 实例但使用不同上下文加密数据非常有用。

重要提示:

  • 密钥管理: 在生产环境中,密钥的生成、存储和管理至关重要。切勿将密钥硬编码在代码中。应使用安全的密钥管理系统(KMS)。
  • Tweak 的选择: Tweak 应尽可能具有唯一性,以提高 FPE 的安全性。对于敏感数据,不建议使用固定或可预测的 Tweak。
  • 性能: FPE 算法通常比传统的块加密算法(如 AES-GCM)计算量更大,因此在对大量数据进行加密时需要考虑其性能影响。
  • NIST 标准: FPE 算法(FF1 和 FF3-1)是 NIST 批准的标准,但在使用时仍然需要了解其限制和最佳实践。

通过这个示例,你应该能够理解 Go 语言中 FPE 的基本用法,并开始将其应用于你的项目中。

Home Archives Categories Tags Statistics
本文总阅读量 次 本站总访问量 次 本站总访客数