Skip to content

Commit 724cabe

Browse files
committed
fix: retry shamir decrypt with share combinations
1 parent 9423bd1 commit 724cabe

2 files changed

Lines changed: 92 additions & 15 deletions

File tree

apis/shamir.go

Lines changed: 57 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -610,13 +610,22 @@ func UploadUserShares(c *fiber.Ctx) error {
610610
status := &GlobalUserSharesStatus
611611

612612
// save Identity Names for User
613-
if utils.InUnorderedSlice(status.UploadedSharesIdentityNames[body.UserID], body.IdentityName) {
614-
return common.BadRequest("您已经上传过,请不要重复上传")
613+
uploadedIdentityNames := status.UploadedSharesIdentityNames[body.UserID]
614+
uploadedIndex := -1
615+
for i, identityName := range uploadedIdentityNames {
616+
if identityName == body.IdentityName {
617+
uploadedIndex = i
618+
break
619+
}
615620
}
616-
status.UploadedSharesIdentityNames[body.UserID] = append(status.UploadedSharesIdentityNames[body.UserID], body.IdentityName)
617621

618622
// save shares
619-
status.UploadedShares[body.UserID] = append(status.UploadedShares[body.UserID], body.Share)
623+
if uploadedIndex >= 0 && uploadedIndex < len(status.UploadedShares[body.UserID]) {
624+
status.UploadedShares[body.UserID][uploadedIndex] = body.Share
625+
} else {
626+
status.UploadedSharesIdentityNames[body.UserID] = append(uploadedIdentityNames, body.IdentityName)
627+
status.UploadedShares[body.UserID] = append(status.UploadedShares[body.UserID], body.Share)
628+
}
620629

621630
if len(status.UploadedSharesIdentityNames[body.UserID]) >= 4 {
622631
status.ShamirUploadReady[body.UserID] = true
@@ -675,27 +684,60 @@ func GetDecryptedUserEmail(c *fiber.Ctx) error {
675684
}
676685
}
677686

678-
email := shamir.Decrypt(status.UploadedShares[targetUserID])
679-
identityName := status.UploadedSharesIdentityNames[targetUserID]
687+
response, ok := decryptUserEmailWithFourShares(
688+
targetUserID,
689+
status.UploadedShares[targetUserID],
690+
status.UploadedSharesIdentityNames[targetUserID],
691+
)
692+
if !ok {
693+
return common.BadRequest("解密失败,请重新输入坐标点")
694+
}
680695

681696
delete(status.UploadedShares, targetUserID)
682697
delete(status.UploadedSharesIdentityNames, targetUserID)
683698
status.ShamirUploadReady[targetUserID] = false
684699

685-
response := DecryptedUserEmailResponse{
686-
UserID: targetUserID,
687-
UserEmail: email,
688-
IdentityNames: identityName,
700+
return c.JSON(response)
701+
}
702+
703+
func decryptUserEmailWithFourShares(userID int, shares shamir.Shares, identityNames []string) (DecryptedUserEmailResponse, bool) {
704+
n := len(shares)
705+
if len(identityNames) < n {
706+
n = len(identityNames)
707+
}
708+
if n < 4 {
709+
return DecryptedUserEmailResponse{}, false
689710
}
690711

691-
// validate email
692712
validate := validator.New()
693-
err = validate.Struct(response)
694-
if err != nil {
695-
return common.BadRequest("解密失败,请重新输入坐标点")
713+
for i := 0; i < n-3; i++ {
714+
for j := i + 1; j < n-2; j++ {
715+
for k := j + 1; k < n-1; k++ {
716+
for l := k + 1; l < n; l++ {
717+
response := DecryptedUserEmailResponse{
718+
UserID: userID,
719+
UserEmail: shamir.Decrypt(shamir.Shares{
720+
shares[i],
721+
shares[j],
722+
shares[k],
723+
shares[l],
724+
}),
725+
IdentityNames: []string{
726+
identityNames[i],
727+
identityNames[j],
728+
identityNames[k],
729+
identityNames[l],
730+
},
731+
}
732+
if validate.Struct(response) == nil {
733+
return response, true
734+
}
735+
}
736+
}
737+
}
696738
}
697739

698-
return c.JSON(response)
740+
return DecryptedUserEmailResponse{}, false
699741
}
700742

701743
// GetDecryptStatusbyUserID godoc

apis/shamir_test.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package apis
2+
3+
import (
4+
"math/big"
5+
"testing"
6+
7+
"auth_next/utils/shamir"
8+
)
9+
10+
func TestDecryptUserEmailWithFourSharesSkipsBadShare(t *testing.T) {
11+
const email = "test@example.com"
12+
13+
shares, err := shamir.Encrypt(email, 5, 4)
14+
if err != nil {
15+
t.Fatal(err)
16+
}
17+
18+
shares[2] = shamir.Share{
19+
X: big.NewInt(12345),
20+
Y: big.NewInt(67890),
21+
}
22+
23+
response, ok := decryptUserEmailWithFourShares(1, shares, []string{"a", "b", "c", "d", "e"})
24+
if !ok {
25+
t.Fatal("expected decrypt to succeed")
26+
}
27+
if response.UserEmail != email {
28+
t.Fatalf("expected email %q, got %q", email, response.UserEmail)
29+
}
30+
for _, identityName := range response.IdentityNames {
31+
if identityName == "c" {
32+
t.Fatal("expected successful identity names to skip bad share")
33+
}
34+
}
35+
}

0 commit comments

Comments
 (0)