@@ -680,37 +680,25 @@ try {
680680 console . log ( ` ✅ NFT owner is now: ${ token . owner_id } ` ) ;
681681 console . log ( ` ✅ Transfer successful: ${ token . owner_id === "bob.test.near" } ` ) ;
682682
683- console . log ( "\n🔐 Step 9: Re-encrypt Secret for Bob" ) ;
684- // Following the TRANSFER section from ENCRYPTED_CONTENT.md:
685-
686- // Re-encrypt the secret_scalar (not AES key!) for Bob
687- const bobCiphertext = elgamalEncrypt ( secretScalar , bobKeys . publicKey ) ;
683+ console . log ( "\n🔑 Step 9: Alice Retrieves Bob's Public Key from Contract" ) ;
684+ // Alice needs Bob's public key to re-encrypt the secret
685+ const bobPubkeyResult = await viewFunction ( "nft.test.near" , "call_js_func" , {
686+ function_name : "get_encryption_pubkey" ,
687+ account_id : "bob.test.near" ,
688+ } ) ;
689+ const bobPubkeyFromContract = bobPubkeyResult . pubkey_base64 ;
690+ console . log ( " ✅ Retrieved Bob's public key from contract" ) ;
691+ console . log ( " - Bob's pubkey:" , bobPubkeyFromContract . substring ( 0 , 16 ) + "..." ) ;
692+ console . log ( " - Matches local:" , bobPubkeyFromContract === bobKeys . publicKey ? "✅ YES" : "❌ NO" ) ;
693+
694+ console . log ( "\n🔐 Step 10: Alice Re-encrypts and Generates ZK Proof" ) ;
695+ // Alice re-encrypts the secret_scalar for Bob's public key (retrieved from contract)
696+ const bobCiphertext = elgamalEncrypt ( secretScalar , bobPubkeyFromContract ) ;
688697 const bobRandomness = bobCiphertext . randomness ;
689- console . log ( " ✅ secret_scalar re -encrypted for Bob" ) ;
698+ console . log ( " ✅ Re -encrypted secret_scalar for Bob" ) ;
690699 console . log ( " - Bob C1:" , bobCiphertext . c1_base64 . substring ( 0 , 16 ) + "..." ) ;
691700 console . log ( " - Bob C2 (point):" , bobCiphertext . c2_base64 . substring ( 0 , 16 ) + "..." ) ;
692701
693- // Verify Bob can decrypt to get secret_point and derive AES key
694- const bobRecoveredSecretPoint = elgamalDecrypt (
695- bobCiphertext . c1_base64 ,
696- bobCiphertext . c2_base64 ,
697- bobKeys . privateKey
698- ) ;
699- const bobRecoveredAesKey = crypto . createHash ( 'sha256' ) . update ( bobRecoveredSecretPoint ) . digest ( ) ;
700-
701- console . log ( " ✅ Bob decrypted secret_point and derived AES key" ) ;
702- console . log ( " - Bob's secret_point matches:" , secretPointBytes . equals ( bobRecoveredSecretPoint ) ? "✅ YES" : "❌ NO" ) ;
703- console . log ( " - Bob's AES key matches:" , aesKey . equals ( bobRecoveredAesKey ) ? "✅ YES" : "❌ NO" ) ;
704-
705- // Bob can now decrypt the content!
706- const bobDecryptedContent = decryptContent (
707- aliceContentData . encrypted_content_base64 ,
708- bobRecoveredAesKey
709- ) ;
710- console . log ( " ✅ Bob can decrypt the content!" ) ;
711- console . log ( " - Content matches:" , contentPlaintext === bobDecryptedContent ? "✅ YES" : "❌ NO" ) ;
712-
713- console . log ( "\n🔐 Step 10: Generate and Verify ZK Proof" ) ;
714702 // Generate zero-knowledge proof that both ciphertexts encrypt the same secret_scalar
715703 const proof = generateReencryptionProof (
716704 secretScalar , // The secret_scalar being encrypted
@@ -721,17 +709,22 @@ try {
721709 bobCiphertext . c1_base64 , // New ciphertext C1 (Bob)
722710 bobCiphertext . c2_base64 , // New ciphertext C2 (Bob)
723711 bobRandomness , // Randomness used for Bob's encryption
724- bobKeys . publicKey // Bob's public key
712+ bobPubkeyFromContract // Bob's public key (from contract)
725713 ) ;
726714 console . log ( " ✅ Generated ZK proof" ) ;
727715
728- // Complete the encrypted transfer with proof verification
716+ console . log ( "\n📤 Step 11: Alice Submits Proof to Complete Transfer" ) ;
717+ // Alice submits the new ciphertext and proof to the contract
718+ console . log ( " 📤 Submitting Bob's new ciphertext:" ) ;
719+ console . log ( " - C1:" , bobCiphertext . c1_base64 . substring ( 0 , 16 ) + "..." ) ;
720+ console . log ( " - C2:" , bobCiphertext . c2_base64 . substring ( 0 , 16 ) + "..." ) ;
721+
729722 const completeResult = await functionCall (
730723 "alice.test.near" ,
731724 "nft.test.near" ,
732725 "call_js_func" ,
733726 {
734- function_name : "complete_encrypted_transfer " ,
727+ function_name : "finalize_reencryption " ,
735728 token_id : "encrypted-nft-1" ,
736729 new_ciphertext_c1_base64 : bobCiphertext . c1_base64 ,
737730 new_ciphertext_c2_base64 : bobCiphertext . c2_base64 ,
@@ -746,15 +739,52 @@ try {
746739 } ,
747740 }
748741 ) ;
749- console . log ( " ✅ ZK proof verified successfully!" ) ;
750- console . log ( " - Transfer completed with cryptographic proof" ) ;
751- console . log ( " - Proof guarantees Alice and Bob have the same secret_scalar" ) ;
742+ console . log ( " ✅ finalize_reencryption result:" , completeResult ) ;
743+ console . log ( " ✅ ZK proof verified on-chain!" ) ;
744+ console . log ( " ✅ Transfer finalized with cryptographic proof" ) ;
745+ console . log ( " ✅ New ciphertext should be stored for Bob" ) ;
746+
747+ console . log ( "\n📥 Step 12: Bob Retrieves Ciphertext from Contract" ) ;
748+ // Bob retrieves the encrypted content data from the contract
749+ const bobContentData = await viewFunction ( "nft.test.near" , "call_js_func" , {
750+ function_name : "get_encrypted_content_data" ,
751+ token_id : "encrypted-nft-1" ,
752+ } ) ;
753+ console . log ( " ✅ Bob retrieved ciphertext from contract" ) ;
754+ console . log ( " - Retrieved C1:" , bobContentData . elgamal_ciphertext . c1_base64 . substring ( 0 , 16 ) + "..." ) ;
755+ console . log ( " - Retrieved C2:" , bobContentData . elgamal_ciphertext . c2_base64 . substring ( 0 , 16 ) + "..." ) ;
756+ console . log ( " - Expected C1: " , bobCiphertext . c1_base64 . substring ( 0 , 16 ) + "..." ) ;
757+ console . log ( " - Expected C2: " , bobCiphertext . c2_base64 . substring ( 0 , 16 ) + "..." ) ;
758+ console . log ( " - Ciphertext updated:" , ( bobContentData . elgamal_ciphertext . c1_base64 === bobCiphertext . c1_base64 ) ? "✅ YES" : "❌ NO" ) ;
759+
760+ console . log ( "\n🔓 Step 13: Bob Decrypts and Accesses Content" ) ;
761+ // Bob decrypts using his private key to get secret_point
762+ const bobRecoveredSecretPoint = elgamalDecrypt (
763+ bobContentData . elgamal_ciphertext . c1_base64 ,
764+ bobContentData . elgamal_ciphertext . c2_base64 ,
765+ bobKeys . privateKey
766+ ) ;
767+ const bobRecoveredAesKey = crypto . createHash ( 'sha256' ) . update ( bobRecoveredSecretPoint ) . digest ( ) ;
768+
769+ console . log ( " ✅ Bob decrypted secret_point and derived AES key" ) ;
770+ console . log ( " - Bob's secret_point matches original:" , secretPointBytes . equals ( bobRecoveredSecretPoint ) ? "✅ YES" : "❌ NO" ) ;
771+ console . log ( " - Bob's AES key matches original:" , aesKey . equals ( bobRecoveredAesKey ) ? "✅ YES" : "❌ NO" ) ;
772+
773+ // Bob can now decrypt the content!
774+ const bobDecryptedContent = decryptContent (
775+ bobContentData . encrypted_content_base64 ,
776+ bobRecoveredAesKey
777+ ) ;
778+ console . log ( " ✅ Bob successfully decrypted the content!" ) ;
779+ console . log ( " - Decrypted content:" , bobDecryptedContent ) ;
780+ console . log ( " - Matches original:" , contentPlaintext === bobDecryptedContent ? "✅ YES" : "❌ NO" ) ;
752781
753- console . log ( "\n💡 What the ZK Proof Proves :" ) ;
754- console . log ( " ✓ Both ciphertexts encrypt the SAME secret_scalar" ) ;
755- console . log ( " ✓ Without revealing secret_scalar to anyone" ) ;
782+ console . log ( "\n💡 What the ZK Proof Proved :" ) ;
783+ console . log ( " ✓ Alice and Bob's ciphertexts encrypt the SAME secret_scalar" ) ;
784+ console . log ( " ✓ Without revealing secret_scalar to anyone (zero-knowledge) " ) ;
756785 console . log ( " ✓ Using Sigma protocol with Fiat-Shamir heuristic" ) ;
757786 console . log ( " ✓ Verified on-chain using Rust Ristretto255 operations" ) ;
787+ console . log ( " ✓ Bob can now access the NFT content securely!" ) ;
758788
759789 console . log ( "\n✅ =================================================" ) ;
760790 console . log ( "✅ ALL TESTS PASSED!" ) ;
0 commit comments