mirror of https://github.com/zlatinb/muwire
wip on signing queries
parent
27aad9d75d
commit
1ce410e943
|
@ -8,7 +8,11 @@ import com.muwire.core.search.SearchEvent
|
|||
import com.muwire.core.search.UIResultBatchEvent
|
||||
import com.muwire.core.search.UIResultEvent
|
||||
|
||||
import net.i2p.crypto.DSAEngine
|
||||
import net.i2p.data.Base64
|
||||
import net.i2p.data.Signature
|
||||
|
||||
import java.nio.charset.StandardCharsets
|
||||
|
||||
import com.googlecode.lanterna.gui2.TextGUIThread
|
||||
import com.googlecode.lanterna.gui2.table.TableModel
|
||||
|
@ -40,20 +44,27 @@ class SearchModel {
|
|||
}
|
||||
|
||||
def searchEvent
|
||||
byte [] payload
|
||||
if (hashSearch) {
|
||||
searchEvent = new SearchEvent(searchHash : root, uuid : UUID.randomUUID(), oobInfohash : true, compressedResults : true)
|
||||
payload = root
|
||||
} else {
|
||||
def replaced = query.toLowerCase().trim().replaceAll(SplitPattern.SPLIT_PATTERN, " ")
|
||||
def terms = replaced.split(" ")
|
||||
def nonEmpty = []
|
||||
terms.each { if (it.length() > 0) nonEmpty << it }
|
||||
payload = String.join(" ", nonEmpty).getBytes(StandardCharsets.UTF_8)
|
||||
searchEvent = new SearchEvent(searchTerms : nonEmpty, uuid : UUID.randomUUID(), oobInfohash: true,
|
||||
searchComments : core.muOptions.searchComments, compressedResults : true)
|
||||
}
|
||||
|
||||
boolean firstHop = core.muOptions.allowUntrusted || core.muOptions.searchExtraHop
|
||||
|
||||
Signature sig = DSAEngine.getInstance().sign(payload, core.spk)
|
||||
|
||||
core.eventBus.publish(new QueryEvent(searchEvent : searchEvent, firstHop : firstHop,
|
||||
replyTo: core.me.destination, receivedOn: core.me.destination,
|
||||
originator : core.me))
|
||||
originator : core.me, sig: sig.data))
|
||||
}
|
||||
|
||||
void unregister() {
|
||||
|
|
|
@ -103,6 +103,8 @@ public class Core {
|
|||
private final Router router
|
||||
|
||||
final AtomicBoolean shutdown = new AtomicBoolean()
|
||||
|
||||
final SigningPrivateKey spk
|
||||
|
||||
public Core(MuWireSettings props, File home, String myVersion) {
|
||||
this.home = home
|
||||
|
@ -180,7 +182,7 @@ public class Core {
|
|||
i2pSession = socketManager.getSession()
|
||||
|
||||
def destination = new Destination()
|
||||
def spk = new SigningPrivateKey(Constants.SIG_TYPE)
|
||||
spk = new SigningPrivateKey(Constants.SIG_TYPE)
|
||||
keyDat.withInputStream {
|
||||
destination.readBytes(it)
|
||||
def privateKey = new PrivateKey()
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package com.muwire.core.connection
|
||||
|
||||
import java.nio.charset.StandardCharsets
|
||||
import java.util.concurrent.BlockingQueue
|
||||
import java.util.concurrent.CountDownLatch
|
||||
import java.util.concurrent.ExecutorService
|
||||
|
@ -10,6 +11,7 @@ import java.util.concurrent.TimeUnit
|
|||
import java.util.concurrent.atomic.AtomicBoolean
|
||||
import java.util.logging.Level
|
||||
|
||||
import com.muwire.core.Constants
|
||||
import com.muwire.core.EventBus
|
||||
import com.muwire.core.MuWireSettings
|
||||
import com.muwire.core.Persona
|
||||
|
@ -21,8 +23,10 @@ import com.muwire.core.trust.TrustLevel
|
|||
import com.muwire.core.trust.TrustService
|
||||
|
||||
import groovy.util.logging.Log
|
||||
import net.i2p.crypto.DSAEngine
|
||||
import net.i2p.data.Base64
|
||||
import net.i2p.data.Destination
|
||||
import net.i2p.data.Signature
|
||||
|
||||
@Log
|
||||
abstract class Connection implements Closeable {
|
||||
|
@ -147,6 +151,8 @@ abstract class Connection implements Closeable {
|
|||
query.replyTo = e.replyTo.toBase64()
|
||||
if (e.originator != null)
|
||||
query.originator = e.originator.toBase64()
|
||||
if (e.sig != null)
|
||||
query.sig = Base64.encode(e.sig)
|
||||
messages.put(query)
|
||||
}
|
||||
|
||||
|
@ -225,6 +231,24 @@ abstract class Connection implements Closeable {
|
|||
boolean compressedResults = false
|
||||
if (search.compressedResults != null)
|
||||
compressedResults = search.compressedResults
|
||||
byte[] sig = null
|
||||
// TODO: make this mandatory at some point
|
||||
if (search.sig != null) {
|
||||
sig = Base64.decode(search.sig)
|
||||
byte [] payload
|
||||
if (infohash != null)
|
||||
payload = infohash
|
||||
else
|
||||
payload = String.join(" ",search.keywords).getBytes(StandardCharsets.UTF_8)
|
||||
def spk = originator.destination.getSigningPublicKey()
|
||||
def signature = new Signature(Constants.SIG_TYPE, sig)
|
||||
if (!DSAEngine.getInstance().verifySig(signature, payload, spk)) {
|
||||
log.info("signature didn't match keywords")
|
||||
return
|
||||
} else
|
||||
log.info("query signature verified")
|
||||
} else
|
||||
log.info("no signature in query")
|
||||
|
||||
SearchEvent searchEvent = new SearchEvent(searchTerms : search.keywords,
|
||||
searchHash : infohash,
|
||||
|
@ -236,7 +260,8 @@ abstract class Connection implements Closeable {
|
|||
replyTo : replyTo,
|
||||
originator : originator,
|
||||
receivedOn : endpoint.destination,
|
||||
firstHop : search.firstHop )
|
||||
firstHop : search.firstHop,
|
||||
sig : sig )
|
||||
eventBus.publish(event)
|
||||
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ class QueryEvent extends Event {
|
|||
Destination replyTo
|
||||
Persona originator
|
||||
Destination receivedOn
|
||||
byte[] sig
|
||||
|
||||
String toString() {
|
||||
"searchEvent: $searchEvent firstHop:$firstHop, replyTo:${replyTo.toBase32()}" +
|
||||
|
|
|
@ -7,7 +7,11 @@ import griffon.core.mvc.MVCGroup
|
|||
import griffon.core.mvc.MVCGroupConfiguration
|
||||
import griffon.inject.MVCMember
|
||||
import griffon.metadata.ArtifactProviderFor
|
||||
import net.i2p.crypto.DSAEngine
|
||||
import net.i2p.data.Base64
|
||||
import net.i2p.data.Signature
|
||||
|
||||
import java.nio.charset.StandardCharsets
|
||||
|
||||
import javax.annotation.Nonnull
|
||||
import javax.inject.Inject
|
||||
|
@ -77,21 +81,27 @@ class MainFrameController {
|
|||
}
|
||||
|
||||
def searchEvent
|
||||
byte [] payload
|
||||
if (hashSearch) {
|
||||
searchEvent = new SearchEvent(searchHash : root, uuid : uuid, oobInfohash: true, compressedResults : true)
|
||||
payload = root
|
||||
} else {
|
||||
// this can be improved a lot
|
||||
def replaced = search.toLowerCase().trim().replaceAll(SplitPattern.SPLIT_PATTERN, " ")
|
||||
def terms = replaced.split(" ")
|
||||
def nonEmpty = []
|
||||
terms.each { if (it.length() > 0) nonEmpty << it }
|
||||
payload = String.join(" ",nonEmpty).getBytes(StandardCharsets.UTF_8)
|
||||
searchEvent = new SearchEvent(searchTerms : nonEmpty, uuid : uuid, oobInfohash: true,
|
||||
searchComments : core.muOptions.searchComments, compressedResults : true)
|
||||
}
|
||||
boolean firstHop = core.muOptions.allowUntrusted || core.muOptions.searchExtraHop
|
||||
|
||||
Signature sig = DSAEngine.getInstance().sign(payload, core.spk)
|
||||
|
||||
core.eventBus.publish(new QueryEvent(searchEvent : searchEvent, firstHop : firstHop,
|
||||
replyTo: core.me.destination, receivedOn: core.me.destination,
|
||||
originator : core.me))
|
||||
originator : core.me, sig : sig.data))
|
||||
}
|
||||
|
||||
void search(String infoHash, String tabTitle) {
|
||||
|
|
Loading…
Reference in New Issue