////////////////////////////////////////////////////////////////////////////////
// Copyright © 2024 xx foundation                                             //
//                                                                            //
// Use of this source code is governed by a license that can be found in the  //
// LICENSE file.                                                              //
////////////////////////////////////////////////////////////////////////////////

package backup

import (
	"bytes"
	"crypto/rand"
	"encoding/hex"
	"reflect"
	"testing"

	"github.com/stretchr/testify/require"

	"gitlab.com/xx_network/crypto/csprng"
	"gitlab.com/xx_network/crypto/signature/rsa"
)

func TestTagVersion(t *testing.T) {
	blob := marshalTagVersion()
	err := checkMarshalledTagVersion(blob)
	require.NoError(t, err)
}

func TestMarshalSaltParams_UnmarshalSaltParams(t *testing.T) {
	salt, _ := MakeSalt(csprng.NewSystemRNG())
	p := DefaultParams()

	marshalledBytes := marshalSaltParams(salt, p)
	unmarshalledSalt, newP, err := unmarshalSaltParams(marshalledBytes)
	if err != nil {
		t.Errorf("unmarshalSaltParams returned an error: %+v", err)
	}

	if !bytes.Equal(salt, unmarshalledSalt) {
		t.Errorf("Unmarshalled salt does not match original."+
			"\nexpected: %v\nreceived: %v", salt, unmarshalledSalt)
	}

	if !reflect.DeepEqual(p, newP) {
		t.Errorf("Unmarshalled Params does not match original."+
			"\nexpected: %+v\nreceived: %+v", p, newP)
	}
}

func TestEncrypt(t *testing.T) {
	rsaPrivKey, err := rsa.GenerateKey(csprng.NewSystemRNG(), 4096)
	require.NoError(t, err)

	backup := &Backup{
		TransmissionIdentity: TransmissionIdentity{
			RSASigningPrivateKey: rsaPrivKey,
		},
	}

	key := make([]byte, 32)
	_, err = rand.Read(key)
	require.NoError(t, err)

	salt := make([]byte, 32)
	_, err = rand.Read(salt)
	require.NoError(t, err)

	_, err = backup.Encrypt(csprng.NewSystemRNG(), key, salt, testParams())
	require.NoError(t, err)
}

func TestDecrypt(t *testing.T) {

	rsaPrivKey, err := rsa.GenerateKey(csprng.NewSystemRNG(), 4096)
	require.NoError(t, err)

	backup := &Backup{
		TransmissionIdentity: TransmissionIdentity{
			RSASigningPrivateKey: rsaPrivKey,
		},
	}

	password := make([]byte, 18)
	_, err = rand.Read(password)
	require.NoError(t, err)

	salt, err := MakeSalt(csprng.NewSystemRNG())
	require.NoError(t, err)

	key := DeriveKey(string(password), salt, testParams())

	ciphertext, err := backup.Encrypt(
		csprng.NewSystemRNG(), key, salt, testParams())
	require.NoError(t, err)

	newbackup := &Backup{}
	err = newbackup.Decrypt(string(password), ciphertext)
	require.NoError(t, err)

	require.Equal(t, newbackup.TransmissionIdentity.RSASigningPrivateKey, backup.TransmissionIdentity.RSASigningPrivateKey)
}

func TestDecryptPrecanned(t *testing.T) {

	keyStr := "d1899ccc9de7a8dc42594fffd9df7edd65b8"
	ciphertextStr := "585841434354424b0092684e68b47b44aa566fec992d09f8b501000000010000000130a7171464baf89c2076198742e7c0aca8d8e4fbfae512a5d27aa95bbdadab25a73be3aca165507366c7d8d6f8367b6236a43450053eb718671b090f8e3f64fa5195195e1fec27c3a1e03c286f142660fc403cfad2a0237c846bf02a1a7d0099ccf24775de5cc7f1ff7a1adcb99a0acce9692da0a8b083556c87b7b1a30942b91266c5332c64e7d777c63811b66accac9dda6669bbaa40c4db0302aedbf535481282300441fdadf8cad96506af2fa091777f709c3d23ece7a79de218cbf1cef0604e98b20657b72ef2b729c57f626564ff482535a0e88f64c2ac625fa52e1006186d72f5c87ff23a0e9a02fd1968a88a5a07fa146c623c0f8d8f31b258f447531201f475799b6b8b5cc87015b15310e9cb0c77f2d96fe724e756c2d20e5b736b93ba89663532b4f11f74918e3145612ad3fc5fa025b36969c5f9ab57c265e7338168f1c3d99c99e011f847fabac5ee78d5e8a1c4b8e8641b8d8a886176de54a7d48a51c0c2545b2940be5df428a30dbb7ab321ee3563c32be7d0e9f1b4bbc3e675f58db9fc0ffdfe426585707bd989b63c10b6db8abf23db38845735b64c4ec376c50d4638614f5f40ea3aba562da2bbbd972f2c77d03771a9b7d7bc1b2078880c638881d8195796d5a8f701d1a44f67a91868108b671267c589def5b7715778bd5a9302683bffda5a98a68f5aa6448d8953018eda89f093c3fb0c317e790a1b0685ab690ab4c97b1e829b8f9fbcd878bab52c38bb7f675ae21bb0a53bf8c68dc8f3ff9aa125353d81a35517e3981e1b706b422d6dfcd7cf624b818b1e7942f8f066b8528b1185e3c0e770edee95bd96e758d0ed864f50b1f9cee661ad2264b4ad4ab0ba0ec3088f8077fa38356600c9bca2fc5c2f6108a9cd2ffdad7626ec8ddc617694af9431fb1c175841ab01af80f9b4542229bfcd527ae888941dc6ff311bd0c8a5317a265f29fd19ebb44dd24354e4158bc1bbecbf3f3bac338378a1004e67ff55e30ca4d1b8e1080e957dfe54b07ba5b7791dd0dc2a95ca1e9d1dc1d32c0502b0f0e0fbacb41973ed9dcc83700081e44598a32f2cab23942a74580550c65d46642fd991accb61c24209d63640104f7d73f85654e68e4dfa3a58b3a99eff376517768ed5105cedebb23927679a6cb3fa8836018b604f0d8e04de7189456b789bcd8ed9e298bfffa1a21455afd5cd485be1eabb09d3fe4ee5792d418ea714a451ecaeedd04dc4b10aa0924194638ae0eb70cd4c94b7f2b02a0cef840da46085c8566f3790851754c0126c38126aca621ddecdc5e2e45a3d82b427a28ac0ae3616c399433dfc133ef7c1c8646e881be25f45e535cd0a6a0ad13179e910f94ea6827c5e5e444b6f7c63ab3554b79b0abd0ef8fb24d9b464b71530e7c57251dff6a540f8156b5b61f8afbad9da5666af4790d12c8a870fe5ee5d73945ffbde9c72b4600d6730d93d5127a1e14480dae10f48470c1e262e48f390b157edc58d9b020d035a456c9d1aebd60fe40d5d6add99907363ecf4cc10e1a99256ca830031e572a199d6c7e7dd8e60c45c236f89ced03a15bdd4167dbfd27c043ddc2b049b68e230500ec6d018b4fd1bb8a6ad06c5956e667001d5e11d057a91909462f5a33af16c90fa5c60a21cd3e931ee2fa90ef0bb2d54bd28642ef71ed4b0bf844510f20de913e82954c6f8357074ba7fbd190105f2c06b50d24a2fc8bc57dbae58dab50bea9872e1789b409d5965e390ae78ff9bc7c3ef0a4a06ffea66cbb12ef825ec15d35c4f33b54896edb7fa42259e73f1530acd1186fa239818e08b8178ba68a0aac8c16d5957e84d36c1b2c6f9f988b324f02526f951842f77a4163e816dda6fc0ae53feccb19ae11d4cb42b3759669e20a77d076fe5cc5bf130a437bcd13b848e9c0a2c2fccff43fa88eecb1964eaa4400de499d30d047b87116e6f8959786fe91afa44c378f1bdcc8f6a5739df0389d86ebd2a30f28244004f22769c10013929add3142a26ed1f7aaf5944f5943af8ee5d810995ce42963785a9dfc60fb2f3c800ec2450c1a3ca27709e7b6d5fb8e50c3e68449793941a38e4b45d107b05a165111060e30935ce6586021464a157657fe63a2d7520267aa58fbc6602b14e9a852c2f15dc7ece82b125611d32f2155ce7465b19345ef0033e084115091f16fe1e213cffca409e5505bf28e7a90cf575b9b3e9f345e61ed12607270b8f054c29d74fa43cbb2926a82567df1d83384406c34c57552fff18a151f4ec2b72d1328bf19e544ef33227387f2baaa41b4821c2dd67fa314780a01217609b821553ecef154ce3993e7658b2af98f565a94e52e7518db97c15e5e509bc867ba2a5080182ef789e6c7bf42d8523a2773b66f9d247d5a7927afc6453f1f34acd1ce3755df95e2eb185d97d8fbd5cbcf16caac712d6327da402328f44e2432a046426caa0c9746666c73e49c5e27096078091c1b9e3a5f28ed1ce1d31aa9f418711a756c34766e17e43e8c98a9c62ca61fa828cf837c89dc1a34075ac238d57e80c435e25b830d4f23d267873ee99a609b7fdb5983fc11f969da80269f311e4852596c334067eacad54efbb4cf6d66b900f1f54615b2c1a0b234883c16b95ed96d2c2f89a347a9c7a2665b2a436319d5bda6555e65929e10afc9fdf6d10bf49de7a8a7c173732a9b172c4d078e05765e9c08a0702d6132860cd059526f97fded2b8e3e0d594b80ca2b1180e83edf15c2e33ad6d104cc6e1303586a991da6d74c620b8cc8fbaaadbb6c2edd4c80a48c4cef3c677287b65303b3e927afa9f039998409c1fba3204988e1108352ce23686a6845cff9a85e51878b47b67a7598cbe68a4408242b66723fe1d53c73b283a16f25253115b0a061cf02c89ff27337210d52ae35049fad43cd2b8426d297b1d00c057a1c81275cd0c7095a3aae227b1fd8f3ba0ee21615bff5bf965a42aa446d1a8dac2929b5cf017a236fc55178d277a6390e1cce3165f263368892a4de660c3b68a36875926478acda68fb4d40d39d6467f97602ff42a13268741ce3097c27a76eb78c960db436fdb5d0d4af6dc4109a241c22facccdaddd3612a665261b36489252839130821df50b29569a95cdbe0f44835251aa68385445d7d35ae0b432be147f8d2e4a769194484876a3c1ddd1b07be0c1a72f2b3ee757872915ab0a1148486070655657d65eefb84b6ff4a7c6db538a8c5a9d1b74ea4ea18bcacbf72fea55b60ed904ea37e7ea975abfa166d8f057b8dba6254b186c80f7e135771a6657a493c1109c5f4fd16f71bf48fc20bc0a1362d61117429ed8d5e23eb6175a23ecd68106161bdef7e97f1b35fbcba8d72245da903ec5e76b53fe582422cd1a218e3135c97e64ddad07b2fde64e38a86f5bdb7f2b19c929f66ebc7c2c2a105462578e80bf864519f68713eb497cb1b262a594ad0a0a628887182e17ac0f420654f99568b72e7721b1505e5125f765f63f63e293da43df6f8c43a076eb7f4b100502c649cf316c1b084c51e644d22c57eabc1a4bfe8c20cb4b851304db71af2c72023d9136a15d3edbe341cf2b9929b6b492b019f38c4d82016b6d9db8760e843dc0d0a8457f5d5f9daa6c35a9660d916f4b39709317f642f7ac0cc3e83f739643eab2b543fc06551c54c7ee1a9975538576b0c5caaec3fb272367c8fd4d79b7315b0d73682b881e824ed950eb9727e7265cdf651a494a7d28a07f3802ba4f854c6470b4c5ea120f256c0699c1f6a7110d911ca03f13d7e4b101e0c54cbc7a2285daa6b5d729ec771983f00ac0ac7158d7f11a67738297438376ea0a81ae8c1f63bc97371088cf7d53da865569286589b6e2e2f3da2142b19b400659464a03d02f6cfdbfbb8df9095bb9d41dba8f86af63af1b124daa3c26eb43446a31cc3b6b99938825b89ce397c86657a2d36f3dba405d0a8e6dfde32c147c7a7ba3d7259db9742973da09e7ae78db5b3db761fc543743a4ba05adeddae78f4a0546bbb266fcb81e3f18dbfff11764376f458785c5ff8c58c923d620d90297349889425b8b074477729abe78e75f6e79c4a38245bbc9bf17594761d6c46ca42ed9a2b12ea2b6ec1b0ebaae6c76280153a6997a3c5b6b92a87516b03a4fac054958aff344c8746f8991e0eddd85c60349525b52a921b4c478347705c13151f32045ac79a1a36ca7bad97bf51ecaa9da69721bd071f27c30d7c804f80996fc7f1d1c4a9e6e20f05812343667b998b866bd0dc188b9057490a348ad72aa2d4c1e4b5a3c02f5a9e6769c978cf995793fe1ca7ee779953daa0d71d8ac7a787f8e0efac68c484b7ab6d215ba2cf4574dca41dc15d7387a3225c03793831aa9f93822e676368515469fba2bf41a4221f991f68e7f901e811ee353aec5192507b34a1ab2de3d058848b66e5be7acf6ce3b2101b95b3af0d5035d20ea840a840a07bb54c4f0aabd17558da827ff14eab98a54e23e2d46b22c23d5d1299526a403acb0ec1da9337dfeed717784f8450a996c703e55904948b9a59b70e57526130f96e8985ae1d0d70db1912e86f1d8065be9a76d22e6eda8e571bf648b30fe5b443b7da91516fb6f0391af208c0f741849042738696b52af773417454418a9cf7513db0540777875c78b844344a3480fa11dcfbe49cc4bcebc0a56c9647e0744e08f6b5ecdf67d3ae382a36dc5a24c94caa399c1613f25a53d4ce81ee1b4ffee8f2d44dde022677948def70415c9baa6d833356ab607d870070878df29319aea635ac74e5622eb987d06e88fd75cdee5f2424375eb7dc1112b0516f351d61eb8de704326c2eded5ad7a0b04ddca20d20c3dd2130e050dcd886c665a50b6652c5f19321a53090a515752a73a896a3b809c0e603d040e96199b932fb07ca0ff3057de8e355578762049f14de531d401d46fc732e90a7e5d6b5254c821c151e032ae095f53a91b63bae4e56aeb2c211f2175e533795083ca6bd04c502ba391e7616ea802d120163b524ccd0773a789dd430838d69b360242a66da0d145d90a23d4ccafdb20bbdafd46f6576606debf76a5a064048ad3ba71f2e3baa0258236d87579a28e6e09e98d307c9742ff8571f81d1bc0b73ac53db494c362c00c46ad63bcb8fb60bdeb6545d282c74afa1629b4b9ad121e6f0c8c778ca7f1b72ab659d8c1995eb9fa985033c80b4324426900511dcc561ab36f08603bfa0e503a2eb2e445f74aaf5b433cdd930dea3425e25e743e76ad87657380455be0d063c793d8968cfc83c0a2278f132df7494a0d855fd5ddf51d2ce9387e0d7ca60551e86b4187aed20b258bd7bd388b666bf0b0f5458e844ba0fb3ea08603b0c4555ec9bf755154f7699ed6deef675e47bbfa7fba97270a17fc94ff92214dbdee3869c19c80035f11f21c4dca354a7bfc0fdce903c3b201268e44b32d80c6496588c182c76f6aa3cca7b5971c199184435d7681141d312a17ac9335517fa7b159d05d6c91b3fa9dc239f8f1cb8869e27338bb16912b965b47106fe225f35d0a27be6a91ceda2476b4690ad2b1fa304a3242bb91e4253eb14358a1e2165e52b401469e76c1e8a4d074b6001d05fd0b27df69cdf2e10af138f46f6e0dad0b1fe986e114b34f5dbda1f04b819b3e3081dc92bf1363defacf839cbf26e6ac29558560003de38c3af1ba5dbb8a408828168e10d69811ba3ea5c171c0f3470cdf51239059b984ad5bfe9845b7fbbbf3619bdc7067a88173801fd46b2f6ff83ab6e3bb188753d9a32ed3d69891bd8657cd5c64f97aa0a62f6feb1a648fb525992c7b81fd3cb7fd3a997659c713d32e98a9bc7be97f3009b13de79be6dbf3a2e11acecfb0d07caae4e5d7f0f85025dcf4fae3a5050dd770592131ee5a3a7589d5dbe02614df21fe4d4e744600e8899875b8452e94f1b2448b0909731d9b8e0259c92cd5815a2fadeeaf835000f3bb02d6c6970ee2fbbfd14f0ab3dfb816d68469e5b0224f88b9f4f8055ffadc91dc0af560448d7099857bf028198a7cb0ec9f995ec1e9476e6ea2127e63577a06671f4447443895aaa19289ce6d5f744763b0ba319031bc76b21e4e0729afcc8ae84ae3352474b2937b3cb36481c80fd060eb9b5825460d38e992cc7dc4c86b5a1e9579f9938b612f038e83af3408ffbcde811ee4b6e218b109413afcbfc1544a04bdce130d2848c936d04ea292f216494091101029d059d5b2f930fd6db86d340801d620c6f97d94447abff1afd2aacc2e07fee97694268515b8be118d27283b292451384985b6ce8e871c7153e3a8d63597ae12ad0078e52c202e6ce10feffad154b8ec52475183f1e0f862196da7409a2a7fd28e2f1b16356df50939711f2f53c51b00946a78b25ab664729c4ac7b1f4da0f49d671424bb8150427053555cc1b16a86ed4c44538e2284f7d54692d473dd70fb65bb7ad24bbdd9c466d67958e58003ab116e528b7749212942b61c6e6198117bae5803cf5e468715414b03c3d98ab88a8d1b08e73aa47fd46b75e8214474d231748bccf9154ad41e80a41746ec20bcd04a6b37d15c42dfadbeb0b7078e4827ebacca3a877f0a8a069af1ebea1ecd082ed933f6f6860351bb9527b356df90a9bd1389fa43b58df2d4aa94d6f98db3953ec96fcde38aaad9c156a20e5d1cdd80e92a5f90ec795c60f61e8a869529e5a0badf8cc712e39770b847223efa128a7a2016aca9b01335441df350cf5e63d28a10511f4c4cd53a01d47d4b4ca5f37422077807c2e3a443e81e3b52dcbb9693a57861faf0caef38aae48b6082329fd4095d38ccecfeeaeda1587458b1340d1de18cbd306395ab60c4b7858ccb0c25a09e72d559f3b97ec9279c288d6a5cd5eba12f4d3586fe52eee3175a906723d8fc5b4965c573badf7ce5d108b9086fe784bc03c98cb03cde5721fa38c8dd3a529413a719bbd93862d681e57560e4a47958131bb946321e5c974673e644b279f5347473c3ba51af9eb7955a2033e31a1bb8b69418223c3977f591e0e775a33805b932cde264e2c6e7107300203eb8d3c00db84dbc2896c2d1bf14d8943b92f4da823be0227853d2bb16af660d70e96dc4d92140fd8e58bf77576d30a3067c4ef26c381a9c916c005520f8c6156788d616db2cb1895fea298a68039e33d9f5940ae48180256a2e2e38734740cc42f1acad6ffa4604a894e2dd6effa38cfae0480db06dd5de3460a07fbafb333139b4c816b4b48ea624e91f5fdc9687845c4be56093bd44c9d3d409916ee7ee047a37c00a4a4674f0c1cfdab7d97f33be345be2801790e306617fda39ef2c5f78ec3984d287fd5c362d7a654c126d7bec081a9d02c9a205bdaee58a9a8cf71c87c3b4edc82a24523dfce590084cc01db43b6b5c6b70fd7700f7e562c7bdc52a114308d08fd93d956224d8ee6d2dc223e88167c574055596958c35960ba529df29b48e9d67136e36fd1313f51580750bde691f5e676b2ac3c99073ff4874a7d1b63025dcf95a2ac1b567288d934bc078a668683b8c17fd3544ae759d7bce11316176a70f58dbe9b1379460612a00480f7fc2c2129fef83bbadcaa8e2e469c936ffcb550aef6d2e4a9934136e4469a23946927bd806c3c9b0600acb564f11bb0ec97207dceb7c8d727569a09a8697c0847c2c645c9cc725f514cf1c7d4fa7196f287ab921ce245a127053557350ad3d1e7b98ca1ba2351fd5c1f9d02b5f81489f1847eea199fe55fa18e914509cc57c42796bd2539c6f36efaea163525f6288357c063720aba6faf73afd2f9bc58b213f17729c6fbf643bd3658c466d5746d2c83c5be99b638802a53feb694f8ce132a49662d4ef49d87bb49c54bfe0ef646d0b4dd2d5ced3bcde69bcde41d7a6621c90c55a227ad5025e8ede4a4d017c5ab3b0e80655e1f51eb2193a401540925c4da0dd709ac4ef07471addf8c15b505bb4a1c218f2b4df6e38bb3759bd582b9f6291422778780a765a56f197335d6d278f70b363d6aaaaf802125d60d004e20bef68422dcb6ac75210639dd4ff60c0fadeb42e5fcec86ea0fb63021bdbcdc6b2e57f912ce5de47f48f807febe33fbe08d0c1ea6f40ea7c775b1652403ccb94ce556f372fdc207d764f1327ea4c9828726d8f5bfa6568142c84526360ccc68df4536b59cc8efb49dcb222cf3d20107b734b446bf89ecf7c2a4f3998c182e5662363e445baeb76b463dacc83163205d230dc69bd071d7794b81aa24b3298a8ef74602bbaecc7f9ca7eb1537d23a69f257c05d3fc7612babb7a43f4d84cc194b9c1648887f7a9382f8477ff56dea76b99f350f88cd95e36450b8e91638fbb566521700e9994b1cad0ab3e7f6afc854b80cefcc8e96ad6f78525be9383386c4f97e844cc85d48402e638fb26d8ddd0a6919a0d42014465175d910eb259a7f8588f766e923da06078a34103ab805332eb2567794ad7347027a2f8a0ac7ddb0d00e6fe2e5bee43d0eb897553a171882f1d2e9c4ee44fd833325bfb2808ab32ebfe768973389eb2b20194bd68915e03349dcac9899ff0b29191e60f2f941fa79453e65d3c303e6f6b9f605b09d0c94035822a139fbd0fa88d74b31cf597187db1c1c31367940067187bc9c9af6ceb0d1240c5e35"

	key, err := hex.DecodeString(keyStr)
	require.NoError(t, err)
	ciphertext, err := hex.DecodeString(ciphertextStr)
	require.NoError(t, err)

	backup := &Backup{}
	err = backup.Decrypt(string(key), ciphertext)
	require.NoError(t, err)
}