feat(coordinator): fix login replay attack (#723)

Co-authored-by: Péter Garamvölgyi <peter@scroll.io>
Co-authored-by: colinlyguo <colinlyguo@scroll.io>
This commit is contained in:
georgehao
2023-08-05 16:58:59 +08:00
committed by GitHub
parent 2a0c7ae6b5
commit a98a2ff4b5
7 changed files with 27 additions and 62 deletions

View File

@@ -5,7 +5,7 @@ import (
"runtime/debug" "runtime/debug"
) )
var tag = "v4.1.0" var tag = "v4.1.1"
var commit = func() string { var commit = func() string {
if info, ok := debug.ReadBuildInfo(); ok { if info, ok := debug.ReadBuildInfo(); ok {

View File

@@ -81,9 +81,11 @@ func (c *CoordinatorApp) MockConfig(store bool) error {
} }
// Reset prover manager config for manager test cases. // Reset prover manager config for manager test cases.
cfg.ProverManager = &coordinatorConfig.ProverManager{ cfg.ProverManager = &coordinatorConfig.ProverManager{
ProversPerSession: 1, ProversPerSession: 1,
Verifier: &coordinatorConfig.VerifierConfig{MockMode: true}, Verifier: &coordinatorConfig.VerifierConfig{MockMode: true},
CollectionTimeSec: 60, CollectionTimeSec: 60,
SessionAttempts: 10,
MaxVerifierWorkers: 4,
} }
cfg.DB.DSN = base.DBImg.Endpoint() cfg.DB.DSN = base.DBImg.Endpoint()
cfg.L2.ChainID = 111 cfg.L2.ChainID = 111

View File

@@ -1,14 +1,14 @@
{ {
"prover_manager": { "prover_manager": {
"provers_per_session": 1, "provers_per_session": 1,
"session_attempts": 2, "session_attempts": 5,
"collection_time_sec": 180, "collection_time_sec": 180,
"verifier": { "verifier": {
"mock_mode": true, "mock_mode": true,
"params_path": "", "params_path": "",
"assets_path": "" "assets_path": ""
}, },
"max_verifier_workers": 10 "max_verifier_workers": 4
}, },
"db": { "db": {
"driver_name": "postgres", "driver_name": "postgres",
@@ -22,6 +22,6 @@
"auth": { "auth": {
"secret": "prover secret key", "secret": "prover secret key",
"challenge_expire_duration_sec": 3600, "challenge_expire_duration_sec": 3600,
"login_expire_duration_sec": 3600 "login_expire_duration_sec": 10
} }
} }

View File

@@ -8,24 +8,19 @@ import (
"scroll-tech/common/database" "scroll-tech/common/database"
) )
const (
defaultNumberOfVerifierWorkers = 10
defaultNumberOfSessionRetryAttempts = 2
)
// ProverManager loads sequencer configuration items. // ProverManager loads sequencer configuration items.
type ProverManager struct { type ProverManager struct {
// The amount of provers to pick per proof generation session. // The amount of provers to pick per proof generation session.
ProversPerSession uint8 `json:"provers_per_session"` ProversPerSession uint8 `json:"provers_per_session"`
// Number of attempts that a session can be retried if previous attempts failed. // Number of attempts that a session can be retried if previous attempts failed.
// Currently we only consider proving timeout as failure here. // Currently we only consider proving timeout as failure here.
SessionAttempts uint8 `json:"session_attempts,omitempty"` SessionAttempts uint8 `json:"session_attempts"`
// Zk verifier config. // Zk verifier config.
Verifier *VerifierConfig `json:"verifier,omitempty"` Verifier *VerifierConfig `json:"verifier"`
// Proof collection time (in seconds). // Proof collection time (in seconds).
CollectionTimeSec int `json:"collection_time_sec"` CollectionTimeSec int `json:"collection_time_sec"`
// Max number of workers in verifier worker pool // Max number of workers in verifier worker pool
MaxVerifierWorkers int `json:"max_verifier_workers,omitempty"` MaxVerifierWorkers int `json:"max_verifier_workers"`
} }
// L2 loads l2geth configuration items. // L2 loads l2geth configuration items.
@@ -38,7 +33,7 @@ type L2 struct {
type Auth struct { type Auth struct {
Secret string `json:"secret"` Secret string `json:"secret"`
ChallengeExpireDurationSec int `json:"challenge_expire_duration_sec"` ChallengeExpireDurationSec int `json:"challenge_expire_duration_sec"`
LoginExpireDurationSec int `json:"token_expire_duration_sec"` // unit: seconds LoginExpireDurationSec int `json:"token_expire_duration_sec"`
} }
// Config load configuration items. // Config load configuration items.
@@ -69,12 +64,5 @@ func NewConfig(file string) (*Config, error) {
return nil, err return nil, err
} }
if cfg.ProverManager.MaxVerifierWorkers == 0 {
cfg.ProverManager.MaxVerifierWorkers = defaultNumberOfVerifierWorkers
}
if cfg.ProverManager.SessionAttempts == 0 {
cfg.ProverManager.SessionAttempts = defaultNumberOfSessionRetryAttempts
}
return cfg, nil return cfg, nil
} }

View File

@@ -14,14 +14,14 @@ func TestConfig(t *testing.T) {
configTemplate := `{ configTemplate := `{
"prover_manager": { "prover_manager": {
"provers_per_session": 1, "provers_per_session": 1,
"session_attempts": %d, "session_attempts": 5,
"collection_time_sec": 180, "collection_time_sec": 180,
"verifier": { "verifier": {
"mock_mode": true, "mock_mode": true,
"params_path": "", "params_path": "",
"agg_vk_path": "" "agg_vk_path": ""
}, },
"max_verifier_workers": %d "max_verifier_workers": 4
}, },
"db": { "db": {
"driver_name": "postgres", "driver_name": "postgres",
@@ -46,8 +46,7 @@ func TestConfig(t *testing.T) {
assert.NoError(t, tmpFile.Close()) assert.NoError(t, tmpFile.Close())
assert.NoError(t, os.Remove(tmpFile.Name())) assert.NoError(t, os.Remove(tmpFile.Name()))
}() }()
config := fmt.Sprintf(configTemplate, defaultNumberOfSessionRetryAttempts, defaultNumberOfVerifierWorkers) _, err = tmpFile.WriteString(configTemplate)
_, err = tmpFile.WriteString(config)
assert.NoError(t, err) assert.NoError(t, err)
cfg, err := NewConfig(tmpFile.Name()) cfg, err := NewConfig(tmpFile.Name())
@@ -88,36 +87,4 @@ func TestConfig(t *testing.T) {
_, err = NewConfig(tmpFile.Name()) _, err = NewConfig(tmpFile.Name())
assert.Error(t, err) assert.Error(t, err)
}) })
t.Run("Default MaxVerifierWorkers", func(t *testing.T) {
tmpFile, err := os.CreateTemp("", "example")
assert.NoError(t, err)
defer func() {
assert.NoError(t, tmpFile.Close())
assert.NoError(t, os.Remove(tmpFile.Name()))
}()
config := fmt.Sprintf(configTemplate, defaultNumberOfSessionRetryAttempts, 0)
_, err = tmpFile.WriteString(config)
assert.NoError(t, err)
cfg, err := NewConfig(tmpFile.Name())
assert.NoError(t, err)
assert.Equal(t, defaultNumberOfVerifierWorkers, cfg.ProverManager.MaxVerifierWorkers)
})
t.Run("Default SessionAttempts", func(t *testing.T) {
tmpFile, err := os.CreateTemp("", "example")
assert.NoError(t, err)
defer func() {
assert.NoError(t, tmpFile.Close())
assert.NoError(t, os.Remove(tmpFile.Name()))
}()
config := fmt.Sprintf(configTemplate, 0, defaultNumberOfVerifierWorkers)
_, err = tmpFile.WriteString(config)
assert.NoError(t, err)
cfg, err := NewConfig(tmpFile.Name())
assert.NoError(t, err)
assert.Equal(t, uint8(defaultNumberOfSessionRetryAttempts), cfg.ProverManager.SessionAttempts)
})
} }

View File

@@ -31,8 +31,16 @@ func (a *AuthController) Login(c *gin.Context) (interface{}, error) {
if err := c.ShouldBind(&login); err != nil { if err := c.ShouldBind(&login); err != nil {
return "", fmt.Errorf("missing the public_key, err:%w", err) return "", fmt.Errorf("missing the public_key, err:%w", err)
} }
// check login parameter's token is equal to bearer token, the Authorization must be existed
// if not exist, the jwt token will intercept it
brearToken := c.GetHeader("Authorization")
if brearToken != "Bearer "+login.Message.Challenge {
return "", fmt.Errorf("check challenge failure for the not equal challenge string")
}
// check the challenge is used, if used, return failure // check the challenge is used, if used, return failure
if err := a.loginLogic.InsertChallengeString(c, login.Signature); err != nil { if err := a.loginLogic.InsertChallengeString(c, login.Message.Challenge); err != nil {
return "", fmt.Errorf("login insert challenge string failure:%w", err) return "", fmt.Errorf("login insert challenge string failure:%w", err)
} }
return login, nil return login, nil

View File

@@ -20,6 +20,6 @@ func NewLoginLogic(db *gorm.DB) *LoginLogic {
} }
// InsertChallengeString insert and check the challenge string is existed // InsertChallengeString insert and check the challenge string is existed
func (l *LoginLogic) InsertChallengeString(ctx *gin.Context, signature string) error { func (l *LoginLogic) InsertChallengeString(ctx *gin.Context, challenge string) error {
return l.challengeOrm.InsertChallenge(ctx, signature) return l.challengeOrm.InsertChallenge(ctx, challenge)
} }