github.com/binbinly/pkg@v0.0.11-0.20240321014439-f4fbf666eb0f/util/xcrypto/rsa_test.go (about)

     1  package xcrypto
     2  
     3  import (
     4  	"crypto/rand"
     5  	"crypto/rsa"
     6  	"crypto/x509"
     7  	"encoding/pem"
     8  	"os"
     9  	"path/filepath"
    10  	"testing"
    11  
    12  	"github.com/stretchr/testify/assert"
    13  )
    14  
    15  const (
    16  	PublicPemFile       = "/test/testdata/rsa_public.pem"
    17  	PublicPKCS1PemFile  = "/test/testdata/rsa_public_pkcs1.pem"
    18  	PrivatePemFile      = "/test/testdata/rsa_private.pem"
    19  	PrivatePKCS1PemFile = "/test/testdata/rsa_private_pkcs1.pem"
    20  )
    21  
    22  var (
    23  	rootDir string
    24  	key     []byte
    25  	origin  []byte
    26  	iv      []byte
    27  )
    28  
    29  func TestMain(m *testing.M) {
    30  	//当前目录
    31  	currDir, _ := os.Getwd()
    32  	rootDir = filepath.Dir(filepath.Dir(currDir))
    33  	// 声明一个16字节的key
    34  	key = []byte("example key 1234")
    35  	// 声明一个随意长度的 需加密内容
    36  	origin = []byte("need to crypto encode test text")
    37  	// 声明一个16字节的iv
    38  	iv = []byte("example iv tests")
    39  	m.Run()
    40  }
    41  
    42  // 生成RSA密钥对
    43  func TestGenerateRSAKey(t *testing.T) {
    44  	// 声明位数
    45  	var bits = 1024
    46  
    47  	// 使用随机数据生成器random生成一对具有指定位数的RSA密钥
    48  	privateKey, err := rsa.GenerateKey(rand.Reader, bits)
    49  
    50  	// 使用指定的位数生成一对多质数的RSA密钥。(质数定义为在大于1的自然数中,除了1和它本身以外不再有其他因数)
    51  	// 虽然公钥可以和二质数情况下的公钥兼容(事实上,不能区分两种公钥),私钥却不行。
    52  	// 因此有可能无法生成特定格式的多质数的密钥对,或不能将生成的密钥用在其他(语言的)代码里
    53  	//privateKey, err := rsa.GenerateMultiPrimeKey(rand.Reader, 5, bits)
    54  
    55  	if err != nil {
    56  		t.Fatal(err)
    57  	}
    58  
    59  	// 将rsa私钥序列化为ASN.1 PKCS#1 DER编码
    60  	derPrivate := x509.MarshalPKCS1PrivateKey(privateKey)
    61  	// 初始化一个PEM编码的结构
    62  	priBlock := &pem.Block{
    63  		Type:  "PRIVATE KEY",
    64  		Bytes: derPrivate,
    65  	}
    66  	// 创建文件,如果文件存在内容重置为空
    67  	file, err := os.Create(rootDir + PrivatePKCS1PemFile)
    68  	if err != nil {
    69  		t.Fatal(err)
    70  	}
    71  	defer file.Close()
    72  
    73  	// 将Block的pem编码写入文件
    74  	err = pem.Encode(file, priBlock)
    75  	if err != nil {
    76  		t.Fatal(err)
    77  	}
    78  	t.Log("RSA-PKCS1私钥生成成功")
    79  
    80  	// 将rsa私钥序列化为PKCS#8 DER编码
    81  	derPrivate8, err := x509.MarshalPKCS8PrivateKey(privateKey)
    82  	if err != nil {
    83  		t.Fatal(err)
    84  	}
    85  
    86  	// 初始化一个PEM编码的结构
    87  	priBlock8 := &pem.Block{
    88  		Type:  "PRIVATE KEY",
    89  		Bytes: derPrivate8,
    90  	}
    91  
    92  	// 创建文件,如果文件存在内容重置为空
    93  	file2, err := os.Create(rootDir + PrivatePemFile)
    94  	if err != nil {
    95  		t.Fatal(err)
    96  	}
    97  	defer file2.Close()
    98  
    99  	// 将Block的pem编码写入文件
   100  	err = pem.Encode(file2, priBlock8)
   101  	if err != nil {
   102  		t.Fatal(err)
   103  	}
   104  	t.Log("RSA-PKCS8私钥生成成功")
   105  
   106  	// 获取公钥
   107  	publicKey := &privateKey.PublicKey
   108  
   109  	// 将公钥序列化为PKIX格式DER编码
   110  	derPublic, err := x509.MarshalPKIXPublicKey(publicKey)
   111  	if err != nil {
   112  		t.Fatal(err)
   113  	}
   114  	// 初始化一个PEM编码的结构
   115  	pubBlock := &pem.Block{
   116  		Type:  "PUBLIC KEY",
   117  		Bytes: derPublic,
   118  	}
   119  
   120  	// 创建文件,如果文件存在内容重置为空
   121  	file3, err := os.Create(rootDir + PublicPemFile)
   122  	if err != nil {
   123  		t.Fatal(err)
   124  	}
   125  	defer file3.Close()
   126  
   127  	// 将Block的pem编码写入文件
   128  	err = pem.Encode(file3, pubBlock)
   129  	if err != nil {
   130  		t.Fatal(err)
   131  	}
   132  	t.Log("RSA-PKIX公钥生成成功")
   133  
   134  	derPublic1 := x509.MarshalPKCS1PublicKey(publicKey)
   135  	// 初始化一个PEM编码的结构
   136  	pubBlock1 := &pem.Block{
   137  		Type:  "PUBLIC KEY",
   138  		Bytes: derPublic1,
   139  	}
   140  	// 创建文件,如果文件存在内容重置为空
   141  	file4, err := os.Create(rootDir + PublicPKCS1PemFile)
   142  	if err != nil {
   143  		t.Fatal(err)
   144  	}
   145  	defer file4.Close()
   146  
   147  	// 将Block的pem编码写入文件
   148  	err = pem.Encode(file4, pubBlock1)
   149  	if err != nil {
   150  		t.Fatal(err)
   151  	}
   152  	t.Log("RSA-PKCS1公钥生成成功")
   153  }
   154  
   155  // 使用PKCS#1v1.5规定的填充方案和RSA公钥加密/私钥解密
   156  func TestRSAPKCS1v15(t *testing.T) {
   157  	// 获取公钥私钥
   158  	privateKey, publicKey, err := getRSAKey()
   159  	if err != nil {
   160  		t.Fatal(err)
   161  	}
   162  
   163  	// rsa公钥加密
   164  	cipherText, err := RsaEncrypt(publicKey, origin)
   165  	if err != nil {
   166  		t.Fatal(err)
   167  	}
   168  
   169  	// rsa私钥解密
   170  	originText, err := RsaDecrypt(privateKey, cipherText)
   171  	if err != nil {
   172  		t.Fatal(err)
   173  	}
   174  	assert.Equal(t, originText, origin)
   175  }
   176  
   177  // RSA-OAEP算法公钥加密/私钥解密
   178  func TestRSAOAEP(t *testing.T) {
   179  	// 获取公钥私钥
   180  	privateKey, publicKey, err := getRSAKey()
   181  	if err != nil {
   182  		t.Fatal(err)
   183  	}
   184  
   185  	// 声明label
   186  	var label = []byte("test")
   187  
   188  	// rsa公钥加密
   189  	cipherText, err := RsaEncryptOAEP(publicKey, origin, label)
   190  	if err != nil {
   191  		t.Fatal(err)
   192  	}
   193  
   194  	// rsa私钥解密
   195  	originText, err := RsaDecryptOAEP(privateKey, cipherText, label)
   196  	if err != nil {
   197  		t.Fatal(err)
   198  	}
   199  	assert.Equal(t, originText, origin)
   200  }
   201  
   202  // RSA私钥签名/公钥验证
   203  func TestRSASignature(t *testing.T) {
   204  	// 获取公钥私钥
   205  	privateKey, publicKey, err := getRSAKey()
   206  	if err != nil {
   207  		t.Fatal(err)
   208  	}
   209  
   210  	// rsa私钥签名
   211  	signature, err := RsaSign(privateKey, origin)
   212  	if err != nil {
   213  		t.Fatal(err)
   214  	}
   215  
   216  	//rsa公钥验签
   217  	if err = RsaVerify(publicKey, origin, signature); err != nil {
   218  		t.Fatal(err)
   219  	}
   220  }
   221  
   222  // RSA-PASS私钥签名/公钥验证
   223  func TestRSASignPass(t *testing.T) {
   224  	// 获取公钥私钥
   225  	privateKey, publicKey, err := getRSAKey()
   226  	if err != nil {
   227  		t.Fatal(err)
   228  	}
   229  
   230  	// 初始化一个 PSS签名 的参数
   231  	var SignOpts = rsa.PSSOptions{SaltLength: 8}
   232  
   233  	// 初始化一个 PSS认证 的参数
   234  	var VerifyOpts = rsa.PSSOptions{SaltLength: rsa.PSSSaltLengthAuto}
   235  	// 当PSS签名参数SaltLength 为 rsa.PSSSaltLengthAuto, PSS认证参数SaltLength 必须为 rsa.PSSSaltLengthAuto
   236  	// 当PSS签名参数SaltLength 为 rsa.PSSSaltLengthEqualsHash, PSS认证参数SaltLength 为 rsa.PSSSaltLengthAuto或rsa.PSSSaltLengthEqualsHash
   237  	// 当PSS签名参数SaltLength 为 指定值时 如8, PSS认证参数SaltLength 为rsa.PSSSaltLengthAuto或8
   238  	//
   239  
   240  	// rsa私钥签名
   241  	signature, err := RsaSignPass(privateKey, origin, &SignOpts)
   242  	if err != nil {
   243  		t.Fatal(err)
   244  	}
   245  
   246  	//rsa公钥验签
   247  	if err = RsaVerifyPass(publicKey, origin, signature, &VerifyOpts); err != nil {
   248  		t.Fatal(err)
   249  	}
   250  }
   251  
   252  func getRSAKey() (privateKey []byte, publicKey []byte, err error) {
   253  
   254  	// 读取publicKey内容
   255  	publicKey, err = os.ReadFile(rootDir + PublicPemFile)
   256  	if err != nil {
   257  		return
   258  	}
   259  	// 读取privateKey内容
   260  	privateKey, err = os.ReadFile(rootDir + PrivatePemFile)
   261  	return
   262  }