pax_global_header 0000666 0000000 0000000 00000000064 13434601454 0014516 g ustar 00root root 0000000 0000000 52 comment=d0a72914b1b13c7766ca764ce93a9d23b473bfe7
woob-d0a72914b1b13c7766ca764ce93a9d23b473bfe7-modules-zerobin/ 0000775 0000000 0000000 00000000000 13434601454 0022603 5 ustar 00root root 0000000 0000000 woob-d0a72914b1b13c7766ca764ce93a9d23b473bfe7-modules-zerobin/modules/ 0000775 0000000 0000000 00000000000 13434601454 0024253 5 ustar 00root root 0000000 0000000 woob-d0a72914b1b13c7766ca764ce93a9d23b473bfe7-modules-zerobin/modules/zerobin/ 0000775 0000000 0000000 00000000000 13434601454 0025723 5 ustar 00root root 0000000 0000000 woob-d0a72914b1b13c7766ca764ce93a9d23b473bfe7-modules-zerobin/modules/zerobin/__init__.py 0000664 0000000 0000000 00000001511 13434601454 0030032 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Copyright(C) 2016 Vincent A
#
# This file is part of a weboob module.
#
# This weboob module is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This weboob module is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this weboob module. If not, see .
from .module import ZerobinModule
__all__ = ['ZerobinModule']
woob-d0a72914b1b13c7766ca764ce93a9d23b473bfe7-modules-zerobin/modules/zerobin/browser.py 0000664 0000000 0000000 00000007051 13434601454 0027763 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Copyright(C) 2016 Vincent A
#
# This file is part of a weboob module.
#
# This weboob module is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This weboob module is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this weboob module. If not, see .
from weboob.browser import PagesBrowser, URL
from weboob.browser.exceptions import HTTPNotFound
from weboob.capabilities.date import DateField
from weboob.capabilities.paste import BasePaste
from .pages import ReadPageZero, ReadPage0, WritePageZero, WritePage0
class ZeroPaste(BasePaste):
expire = DateField('Expire date')
@property
def page_url(self):
return self.url
class ZerobinBrowser(PagesBrowser):
BASEURL = 'https://zerobin.net/'
read_page_zero = URL(r'/\?(?P[\w+-]+)$', ReadPageZero)
read_page_0 = URL(r'/paste/(?P[\w+-]+)$', ReadPage0)
write_page_zero = URL('.*', WritePageZero)
write_page_0 = URL('.*', WritePage0)
def __init__(self, baseurl, opendiscussion, *args, **kwargs):
super(ZerobinBrowser, self).__init__(*args, **kwargs)
self.BASEURL = baseurl
self.opendiscussion = opendiscussion
def _find_page(self, subid):
for page in (self.read_page_0, self.read_page_zero):
try:
page.go(id=subid)
except HTTPNotFound:
continue
if self.page.has_paste():
return self.url
else:
continue
def get_paste(self, id):
if id.startswith('http://') or id.startswith('https://'):
url = id
server_url, key = url.split('#')
m = self.read_page_0.match(server_url) or self.read_page_zero.match(server_url)
if not m:
return
subid = m.group('id')
id = '%s#%s' % (subid, key)
self.location(server_url)
if not (self.read_page_zero.is_here() or self.read_page_0.is_here()):
return
elif not self.page.has_paste():
return
else:
subid, key = id.split('#')
server_url = self._find_page(subid)
if not server_url:
return
url = '%s#%s' % (server_url, key)
ret = ZeroPaste(id)
ret.url = url
ret.contents = self.page.decode_paste(key)
ret.public = False
ret.title = self.page.params['id']
if hasattr(self.page, 'get_expire'):
ret.expire = self.page.get_expire()
# TODO impl in ReadPage0
return ret
def can_post(self, contents, max_age):
self.location(self.BASEURL)
if max_age not in self.page.AGES:
return 0
# TODO reject binary files on zerobin?
return 1
def post_paste(self, p, max_age):
self.location(self.BASEURL)
p.url = self.page.post(p.contents, max_age)
server_url, key = p.url.split('#')
m = self.read_page_0.match(server_url) or self.read_page_zero.match(server_url)
p.title = m.group('id')
p.id = '%s#%s' % (p.title, key)
woob-d0a72914b1b13c7766ca764ce93a9d23b473bfe7-modules-zerobin/modules/zerobin/crypto.py 0000664 0000000 0000000 00000006243 13434601454 0027622 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Copyright(C) 2016 Vincent A
#
# This file is part of a weboob module.
#
# This weboob module is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This weboob module is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this weboob module. If not, see .
from base64 import b64decode, b64encode
from collections import OrderedDict
import math
from os import urandom
from Cryptodome.Cipher import AES
from Cryptodome.Protocol.KDF import PBKDF2
from Cryptodome.Hash import SHA256
from Cryptodome.Hash import HMAC
def log2(n):
return math.log(n, 2)
def encrypt(plaintext):
iv = urandom(16)
salt = urandom(8)
iterations = 1000
ks = 128
ts = 64
hash_func = lambda k, s: HMAC.new(k, s, SHA256).digest()
password = b64encode(urandom(32))
key = PBKDF2(password, salt=salt, count=iterations, prf=hash_func)
smalliv = trunc_iv(iv, plaintext, 0)
cipher = AES.new(key, mode=AES.MODE_CCM, nonce=smalliv, mac_len=ts // 8)
ciphertext = b''.join(cipher.encrypt_and_digest(plaintext))
# OrderedDict because 0bin is a piece of shit requiring "iv" as the first key
return password.decode('ascii'), OrderedDict([
('iv', b64encode(iv).decode('ascii')),
('v', 1),
('iter', iterations),
('ks', ks),
('ts', ts),
('mode', 'ccm'),
('adata', ''),
('cipher', 'aes'),
('salt', b64encode(salt).decode('ascii')),
('ct', b64encode(ciphertext).decode('ascii')),
])
def trunc_iv(iv, t, tl):
ol = len(t) - tl
if ol <= 0:
oll = 2
else:
oll = int(max(2, math.ceil(log2(ol) / 8.)))
assert oll <= 4
if oll < 15 - len(iv):
ivl = len(iv)
else:
ivl = 15 - oll
iv = iv[:ivl]
return iv
def decrypt(secretkey, params):
iv = b64decode(params['iv'])
salt = b64decode(params['salt'])
#~ keylen = params.get('ks', 128) // 8 # FIXME use somewhere?
taglen = params.get('ts', 64) // 8
iterations = params.get('iter', 1000)
data = b64decode(params['ct'])
ciphertext = data[:-taglen]
tag = data[-taglen:]
if params.get('adata'):
raise NotImplementedError('authenticated data support is not implemented')
iv = trunc_iv(iv, ciphertext, taglen)
hash_func = lambda k, s: HMAC.new(k, s, SHA256).digest()
key = PBKDF2(secretkey, salt=salt, count=iterations, prf=hash_func)
mode_str = params.get('mode', 'ccm')
mode = dict(ccm=AES.MODE_CCM)[mode_str]
if mode_str == 'ccm':
cipher = AES.new(key, mode=AES.MODE_CCM, nonce=iv, mac_len=taglen)
else:
cipher = AES.new(key, mode=mode, iv=iv)
decrypted = cipher.decrypt_and_verify(ciphertext, tag)
return decrypted
woob-d0a72914b1b13c7766ca764ce93a9d23b473bfe7-modules-zerobin/modules/zerobin/favicon.png 0000664 0000000 0000000 00000011437 13434601454 0030064 0 ustar 00root root 0000000 0000000 PNG
IHDR >a bKGD pHYs tIMEIcI<