forked from electricdusk/rushlink
parent
1c09bb0a71
commit
6d3e8028cb
20
handlers.go
20
handlers.go
@ -22,6 +22,20 @@ const (
|
||||
// formParseMaxMemory value is based on the default value that is used in
|
||||
// Request.ParseMultipartForm.
|
||||
formParseMaxMemory = 32 << 20 // 32 MB
|
||||
|
||||
// highOnlineEntropy is the desired entropy of an "unguessable" paste URL
|
||||
// (in bits). It should be chosen such that it should be hard for an
|
||||
// attacker to find *any* key that should not be found.
|
||||
// It is desired that the probability to guess a good key is small.
|
||||
//
|
||||
// [ amount of pastes ]
|
||||
// Pr[ good key ] = ---------------------------
|
||||
// [ amount of possible keys ]
|
||||
//
|
||||
// So with a conservative [ amount of pastes ] = 2^32 (= 4 billion), and
|
||||
// an [ amount of possible keys ] = 2^80 then the probability of a correct
|
||||
// guess is 2^-48.
|
||||
highOnlineEntropy = 80
|
||||
)
|
||||
|
||||
type viewPaste uint
|
||||
@ -369,7 +383,11 @@ func shortenURL(tx *bolt.Tx, userURL *url.URL) (*db.Paste, error) {
|
||||
// Add a paste (of any kind) to the database with arbitrary content.
|
||||
func shorten(tx *bolt.Tx, ty db.PasteType, content []byte) (*db.Paste, error) {
|
||||
// Generate the paste key
|
||||
pasteKey, err := db.GeneratePasteKey(tx)
|
||||
var keyEntropy int
|
||||
if ty == db.PasteTypeFileUpload || ty == db.PasteTypePaste {
|
||||
keyEntropy = highOnlineEntropy
|
||||
}
|
||||
pasteKey, err := db.GeneratePasteKey(tx, keyEntropy)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "generating paste key")
|
||||
}
|
||||
|
@ -164,10 +164,13 @@ func (p *Paste) RedirectURL() *url.URL {
|
||||
return urlParse
|
||||
}
|
||||
|
||||
// GeneratePasteKey generates a key until it is not in the database, the
|
||||
// running time of this function is in O(log N), where N is the amount of
|
||||
// GeneratePasteKey generates a new paste key. It will ensure that the newly
|
||||
// generated paste key does not already exist in the database.
|
||||
// The running time of this function is in O(log N), where N is the amount of
|
||||
// keys stored in the url-shorten database.
|
||||
func GeneratePasteKey(tx *bolt.Tx) (string, error) {
|
||||
// In tx, a Bolt transaction is given. Use minimumEntropy to set the mimimum
|
||||
// guessing entropy of the generated key.
|
||||
func GeneratePasteKey(tx *bolt.Tx, minimumEntropy int) (string, error) {
|
||||
pastesBucket := tx.Bucket([]byte(BucketPastes))
|
||||
if pastesBucket == nil {
|
||||
return "", errors.Errorf("bucket %v does not exist", BucketPastes)
|
||||
@ -177,7 +180,7 @@ func GeneratePasteKey(tx *bolt.Tx) (string, error) {
|
||||
var key string
|
||||
for {
|
||||
var err error
|
||||
key, err = generatePasteKeyInner(epoch)
|
||||
key, err = generatePasteKeyInner(epoch, minimumEntropy)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "url-key generation failed")
|
||||
}
|
||||
@ -203,8 +206,23 @@ func GeneratePasteKey(tx *bolt.Tx) (string, error) {
|
||||
return key, nil
|
||||
}
|
||||
|
||||
func generatePasteKeyInner(epoch int) (string, error) {
|
||||
urlKey := make([]byte, 4+epoch)
|
||||
// generatePasteKeyInner generates a new paste key, but leaves the
|
||||
// uniqueness and is-reserved checks to the caller. That is, it only
|
||||
// generates a random key in the correct (syntactical) format.
|
||||
// Both epoch and entropy can be used to set the key length. Epoch is used
|
||||
// to prevent collisions in retrying to generate new keys. Entropy (in bits)
|
||||
// is used to ensure that a new key has at least some amount of guessing
|
||||
// entropy.
|
||||
func generatePasteKeyInner(epoch, entropy int) (string, error) {
|
||||
minKeyLen := 4
|
||||
entropyEpoch := entropy
|
||||
entropyEpoch -= minKeyLen * 6 // First 4 characters provide 24 bits.
|
||||
entropyEpoch++ // One bit less because of '0' bit.
|
||||
entropyEpoch = (entropyEpoch-1)/5 + 1 // 5 bits for every added epoch.
|
||||
if epoch < entropyEpoch {
|
||||
epoch = entropyEpoch
|
||||
}
|
||||
urlKey := make([]byte, minKeyLen+epoch)
|
||||
_, err := rand.Read(urlKey)
|
||||
if err != nil {
|
||||
return "", err
|
||||
|
Loading…
Reference in New Issue
Block a user