package pbkd

import (
	"bytes"
	"fmt"
	"testing"

	"golang.org/x/crypto/pbkdf2"
	"xdx.jelly/xgcl/grand"

	"xdx.jelly/xgcl/sm/sm3"
)

func TestPbkdfHF(t *testing.T) {
	password := "1234567812345678"
	salt := []byte("12345678")
	key, err := kdf(newPrfHmacSm3([]byte(password)), salt, 1000, 16)
	if err != nil {
		t.Fatal("PBKD failed")
	}
	fmt.Printf("%x\n", key)
}

func TestPbkdf2(t *testing.T) {
	password := "12345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678"
	salt := []byte("12345678")
	key, err := PbkdfWithHmacSm3([]byte(password), salt, 1000, 16)
	if err != nil {
		t.Fatal("PBKD failed")
	}

	key2 := pbkdf2.Key([]byte(password), salt, 1000, 16, sm3.New)
	if !bytes.Equal(key, key2) {
		t.Logf("%x\n", key)
		t.Logf("%x\n", key2)
	}
}

func TestPbkdf(t *testing.T) {
	password := "passsword"
	salt := []byte("12345678")
	key, err := PbkdfWithHmacSm3([]byte(password), salt, 1000, 16)
	key2 := pbkdf2.Key([]byte(password), salt, 1000, 16, sm3.New)
	if err != nil {
		t.Fatal("PBKD failed")
	}
	t.Logf("%x\n", key)  //b30fea078d13ba4e2199936a2f593f9d
	t.Logf("%x\n", key2) //b30fea078d13ba4e2199936a2f593f9d
}

func TestPbes(t *testing.T) {
	password := []byte("12345678")
	salt := grand.GetRandom(16)
	data := []byte("abcdefghabcdefgh") // 16 bytes
	iv := grand.GetRandom(16)
	pbes, err := NewPbesWithSm4Cbc(password, salt, MildCount, iv)
	if err != nil {
		t.Fatal("pbes failed")
	}

	var buf bytes.Buffer
	for i := 0; i < 2; i++ {
		c, err := pbes.EncryptBlocks(nil, data)
		if err != nil {
			t.Fatal("pbes failed")
		}
		buf.Write(c)
	}
	// last block, padding
	c, err := pbes.EncryptWithPadding(data)
	if err != nil {
		t.Fatal("pbes failed")
	}
	buf.Write(c)
	cipherText := buf.Bytes()
	fmt.Printf("CipherText = %02x\n", cipherText)

	// decrypt - 需要重置IV
	pbes.ResetIv(iv)
	plainText, err := pbes.DecryptWithPadding(cipherText)
	if err != nil {
		t.Fatal("pbes failed")
	}

	fmt.Printf("plainText = %s\n", plainText)
	for i := 0; i < len(plainText)/16; i++ {
		if bytes.Compare(plainText[i*16:(i+1)*16], data) != 0 {
			t.Fatal("pbes failed")
		}
	}

}

func TestPbmac(t *testing.T) {
	password := []byte("12345678")
	salt := grand.GetRandom(16)
	data := []byte("abcdefgh")
	pbmac, err := NewPbmacWithHmacSm3(password, salt, MildCount)
	if err != nil {
		t.Fatal("pbmac failed")
	}

	mac, err := pbmac.ComputeMAC(data)
	if err != nil {
		t.Fatal("compute mac failed")
	}
	fmt.Printf("Mac: %02x\n", mac)
	err = pbmac.VerifyMAC(mac, data)
	if err != nil {
		t.Fatal("verify mac failed")
	}
}
