[#1093] Mailserver compatible with sync AND async keys (#1096)

This commit is contained in:
Adrià Cidre 2018-07-16 11:07:17 +02:00 committed by GitHub
parent bfbb02019f
commit 9ce96baf5d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 90 additions and 21 deletions

View File

@ -86,7 +86,8 @@ type WMailServer struct {
db dbImpl db dbImpl
w *whisper.Whisper w *whisper.Whisper
pow float64 pow float64
filter *whisper.Filter symFilter *whisper.Filter
asymFilter *whisper.Filter
muLimiter sync.RWMutex muLimiter sync.RWMutex
limiter *limiter limiter *limiter
@ -154,7 +155,8 @@ func (s *WMailServer) setupLimiter(limit time.Duration) {
// setupRequestMessageDecryptor setup a Whisper filter to decrypt // setupRequestMessageDecryptor setup a Whisper filter to decrypt
// incoming Whisper requests. // incoming Whisper requests.
func (s *WMailServer) setupRequestMessageDecryptor(config *params.WhisperConfig) error { func (s *WMailServer) setupRequestMessageDecryptor(config *params.WhisperConfig) error {
var filter whisper.Filter s.symFilter = nil
s.asymFilter = nil
if config.MailServerPassword != "" { if config.MailServerPassword != "" {
keyID, err := s.w.AddSymKeyFromPassword(config.MailServerPassword) keyID, err := s.w.AddSymKeyFromPassword(config.MailServerPassword)
@ -167,12 +169,12 @@ func (s *WMailServer) setupRequestMessageDecryptor(config *params.WhisperConfig)
return fmt.Errorf("save symmetric key: %v", err) return fmt.Errorf("save symmetric key: %v", err)
} }
filter = whisper.Filter{KeySym: symKey} s.symFilter = &whisper.Filter{KeySym: symKey}
} else if config.MailServerAsymKey != nil {
filter = whisper.Filter{KeyAsym: config.MailServerAsymKey}
} }
s.filter = &filter if config.MailServerAsymKey != nil {
s.asymFilter = &whisper.Filter{KeyAsym: config.MailServerAsymKey}
}
return nil return nil
} }
@ -357,13 +359,29 @@ func (s *WMailServer) sendHistoricMessageResponse(peer *whisper.Peer, request *w
return s.w.SendHistoricMessageResponse(peer, payload) return s.w.SendHistoricMessageResponse(peer, payload)
} }
// openEnvelope tries to decrypt an envelope, first based on asymetric key (if
// provided) and second on the symetric key (if provided)
func (s *WMailServer) openEnvelope(request *whisper.Envelope) *whisper.ReceivedMessage {
if s.asymFilter != nil {
if d := request.Open(s.asymFilter); d != nil {
return d
}
}
if s.symFilter != nil {
if d := request.Open(s.symFilter); d != nil {
return d
}
}
return nil
}
// validateRequest runs different validations on the current request. // validateRequest runs different validations on the current request.
func (s *WMailServer) validateRequest(peerID []byte, request *whisper.Envelope) (bool, uint32, uint32, []byte, uint32, cursorType) { func (s *WMailServer) validateRequest(peerID []byte, request *whisper.Envelope) (bool, uint32, uint32, []byte, uint32, cursorType) {
if s.pow > 0.0 && request.PoW() < s.pow { if s.pow > 0.0 && request.PoW() < s.pow {
return false, 0, 0, nil, 0, nil return false, 0, 0, nil, 0, nil
} }
decrypted := request.Open(s.filter) decrypted := s.openEnvelope(request)
if decrypted == nil { if decrypted == nil {
log.Warn("Failed to decrypt p2p request") log.Warn("Failed to decrypt p2p request")
return false, 0, 0, nil, 0, nil return false, 0, 0, nil, 0, nil

View File

@ -39,6 +39,7 @@ const powRequirement = 0.00001
var keyID string var keyID string
var seed = time.Now().Unix() var seed = time.Now().Unix()
var testPayload = []byte("test payload")
type ServerTestParams struct { type ServerTestParams struct {
topic whisper.TopicType topic whisper.TopicType
@ -191,25 +192,66 @@ func (s *MailserverSuite) TestSetupRequestMessageDecryptor() {
config = *s.config config = *s.config
s.NoError(config.ReadMailServerPasswordFile()) s.NoError(config.ReadMailServerPasswordFile())
s.NoError(s.server.Init(s.shh, &config)) s.NoError(s.server.Init(s.shh, &config))
s.NotNil(s.server.filter.KeySym) s.Require().NotNil(s.server.symFilter)
s.Nil(s.server.filter.KeyAsym) s.NotNil(s.server.symFilter.KeySym)
s.Nil(s.server.asymFilter)
s.server.Close() s.server.Close()
// AsymKey can also be used // AsymKey can also be used
config = *s.config config = *s.config
s.NoError(config.ReadMailServerAsymKeyFile()) s.NoError(config.ReadMailServerAsymKeyFile())
s.NoError(s.server.Init(s.shh, &config)) s.NoError(s.server.Init(s.shh, &config))
s.Nil(s.server.filter.KeySym) // important: symmetric key should be nil s.Nil(s.server.symFilter) // important: symmetric filter should be nil
s.Equal(config.MailServerAsymKey, s.server.filter.KeyAsym) s.Require().NotNil(s.server.asymFilter)
s.Equal(config.MailServerAsymKey, s.server.asymFilter.KeyAsym)
s.server.Close() s.server.Close()
// when both Password and AsymKey are set, Password has a preference // when Password and AsymKey are set, both are supported
config = *s.config config = *s.config
s.NoError(config.ReadMailServerPasswordFile()) s.NoError(config.ReadMailServerPasswordFile())
s.NoError(config.ReadMailServerAsymKeyFile()) s.NoError(config.ReadMailServerAsymKeyFile())
s.NoError(s.server.Init(s.shh, &config)) s.NoError(s.server.Init(s.shh, &config))
s.NotNil(s.server.filter.KeySym) s.Require().NotNil(s.server.symFilter)
s.Nil(s.server.filter.KeyAsym) s.NotNil(s.server.symFilter.KeySym)
s.NotNil(s.server.asymFilter.KeyAsym)
s.server.Close()
}
func (s *MailserverSuite) TestOpenEnvelopeWithSymKey() {
// Setup the server with a sym key
config := *s.config
s.NoError(config.ReadMailServerPasswordFile())
s.NoError(s.server.Init(s.shh, &config))
// Prepare a valid envelope
s.Require().NotNil(s.server.symFilter)
symKey := s.server.symFilter.KeySym
env, err := generateEnvelopeWithKeys(time.Now(), symKey, nil)
s.Require().NoError(err)
// Test openEnvelope with a valid envelope
d := s.server.openEnvelope(env)
s.NotNil(d)
s.Equal(testPayload, d.Payload)
s.server.Close()
}
func (s *MailserverSuite) TestOpenEnvelopeWithAsymKey() {
// Setup the server with an asymetric key
config := *s.config
s.NoError(config.ReadMailServerAsymKeyFile())
s.NoError(s.server.Init(s.shh, &config))
// Prepare a valid envelope
s.Require().NotNil(s.server.asymFilter)
pubKey := s.server.asymFilter.KeyAsym.PublicKey
env, err := generateEnvelopeWithKeys(time.Now(), nil, &pubKey)
s.Require().NoError(err)
// Test openEnvelope with a valid asymetric key
d := s.server.openEnvelope(env)
s.NotNil(d)
s.Equal(testPayload, d.Payload)
s.server.Close() s.server.Close()
} }
@ -538,16 +580,20 @@ func (s *MailserverSuite) createRequest(p *ServerTestParams) *whisper.Envelope {
return env return env
} }
func generateEnvelope(sentTime time.Time) (*whisper.Envelope, error) { func generateEnvelopeWithKeys(sentTime time.Time, keySym []byte, keyAsym *ecdsa.PublicKey) (*whisper.Envelope, error) {
h := crypto.Keccak256Hash([]byte("test sample data"))
params := &whisper.MessageParams{ params := &whisper.MessageParams{
KeySym: h[:],
Topic: whisper.TopicType{0x1F, 0x7E, 0xA1, 0x7F}, Topic: whisper.TopicType{0x1F, 0x7E, 0xA1, 0x7F},
Payload: []byte("test payload"), Payload: testPayload,
PoW: powRequirement, PoW: powRequirement,
WorkTime: 2, WorkTime: 2,
} }
if len(keySym) > 0 {
params.KeySym = keySym
} else if keyAsym != nil {
params.Dst = keyAsym
}
msg, err := whisper.NewSentMessage(params) msg, err := whisper.NewSentMessage(params)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to create new message with seed %d: %s", seed, err) return nil, fmt.Errorf("failed to create new message with seed %d: %s", seed, err)
@ -559,3 +605,8 @@ func generateEnvelope(sentTime time.Time) (*whisper.Envelope, error) {
return env, nil return env, nil
} }
func generateEnvelope(sentTime time.Time) (*whisper.Envelope, error) {
h := crypto.Keccak256Hash([]byte("test sample data"))
return generateEnvelopeWithKeys(sentTime, h[:], nil)
}