Skip to content

Commit 96433c6

Browse files
authored
Merge pull request #18 from aviaryan/v2
v2
2 parents b71289d + 7857026 commit 96433c6

File tree

10 files changed

+1046
-31
lines changed

10 files changed

+1046
-31
lines changed

README.markdown

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
Sublime Notebook :memo:
33
</h1>
44

5-
**v1.0**
5+
**v2.0**
66

77
Sublime Notebook is an attempt to use Sublime Text as a complete note taking application.
88

@@ -25,7 +25,7 @@ The result is this project, a wrapper/idea that converts my favorite text editor
2525

2626
* Faaaast Search across all notes (thanks to Sublime Text)
2727
* Hierarchical organization and display of notes
28-
* Password based encryption for notes
28+
* Password based encryption for notes (thanks to [pyAES](https://github.com/ricmoo/pyaes))
2929
* Cloud sync (Dropbox, Google Drive, Box, etc)
3030
* Periodic git backup (to Github, Gitlab, your own private git server, etc)
3131
* Markdown based markup and code syntax highlighting

notebook.sublime-project

Lines changed: 33 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,32 +2,49 @@
22
"build_systems":
33
[
44
{
5+
"linux":
6+
{
7+
"shell_cmd": "gnome-terminal -e './manager.py; exec bash\"'"
8+
},
59
"name": "manager.py",
6-
"working_dir": "${project_path}",
7-
"osx": {
10+
"osx":
11+
{
812
"shell_cmd": "open -a Terminal.app ${project_path}"
913
},
10-
"linux": {
11-
// http://stackoverflow.com/questions/21196077/sublime-text-3-compile-program-and-run-in-terminal
12-
"shell_cmd": "gnome-terminal -e './manager.py; exec bash\"'"
14+
"windows":
15+
{
16+
"cmd":
17+
[
18+
"start",
19+
"cmd",
20+
"/k",
21+
"python manager.py"
22+
],
23+
"shell": true
1324
},
14-
"windows": {
15-
// http://stackoverflow.com/questions/19942347/run-program-in-cmd-mode-after-building-from-sublime-text-2
16-
"cmd": ["start", "cmd", "/k", "python manager.py"],
17-
"shell": true,
18-
}
25+
"working_dir": "${project_path}"
1926
}
2027
],
2128
"folders":
2229
[
2330
{
24-
"path": ".",
25-
"folder_exclude_patterns": ["__pycache__"],
26-
"file_exclude_patterns": ["*.pyc"]
31+
"file_exclude_patterns":
32+
[
33+
"*.pyc",
34+
"////sublime_notebook/*.py"
35+
],
36+
"folder_exclude_patterns":
37+
[
38+
"__pycache__",
39+
".release",
40+
"////sublime_notebook/pyaes"
41+
],
42+
"path": "."
2743
}
2844
],
29-
"settings": {
30-
"word_wrap": true,
31-
"margin": 20
45+
"settings":
46+
{
47+
"margin": 20,
48+
"word_wrap": true
3249
}
3350
}

sublime_notebook/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
SETTINGS_PATH = 'sublime_notebook/settings.json'
2-
VERSION = 1.0
2+
VERSION = 2.0

sublime_notebook/cryptlib.py

Lines changed: 54 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,21 @@
11
import base64
22
import os
3+
from traceback import print_exc
34
import re
45
from getpass import getpass
56
from .settings import Settings
67
from .message import print_err
8+
from .pyaes import AESModeOfOperationCTR
79

810

911
EXTRA_STR = 'ENCo0D#DT{xTCh$cKe>'
1012
ENCODED_IDF = '=*=EnC0d3dH3aDer==*'
13+
EXTRA_STR_2 = '3NCo0D#DT{xTCh$cKe>'
14+
ENCODED_IDF_2 = '=*=3nC0d3dH3aDer==*'
1115

1216
# Vigenere's Cipher: http://stackoverflow.com/a/38223403
1317

14-
def encode(key, clear):
18+
def encode_1(key, clear):
1519
if clear.startswith(ENCODED_IDF): # already encoded, no need to encode
1620
return clear
1721
clear += EXTRA_STR # used to check if decrypt is correct
@@ -24,7 +28,7 @@ def encode(key, clear):
2428
return ENCODED_IDF + base64.urlsafe_b64encode("".join(enc).encode()).decode()
2529

2630

27-
def decode(key, enc):
31+
def decode_1(key, enc):
2832
st = ''
2933
if not enc.startswith(ENCODED_IDF): # not encoded, so not decode
3034
return enc
@@ -44,6 +48,40 @@ def decode(key, enc):
4448
return st[:-1 * len(EXTRA_STR)]
4549

4650

51+
def encode(key, clear):
52+
if clear.startswith(ENCODED_IDF) or clear.startswith(ENCODED_IDF_2): # already encoded, no need to encode
53+
return clear
54+
clear += EXTRA_STR_2 # used to check if decrypt is correct
55+
# encrypt string
56+
aes = AESModeOfOperationCTR(key_32(key))
57+
clear = bytes(clear, 'utf8') # everyone writes in utf8
58+
ciphertext = aes.encrypt(clear)
59+
return ENCODED_IDF_2 + base64.urlsafe_b64encode(ciphertext).decode('iso-8859-1')
60+
61+
62+
def decode(key, enc):
63+
st = ''
64+
if not (enc.startswith(ENCODED_IDF_2) or enc.startswith(ENCODED_IDF)): # not encoded, so not decode
65+
return enc
66+
if enc.startswith(ENCODED_IDF): # old version
67+
return decode_1(key, enc)
68+
# new version
69+
enc = enc[len(ENCODED_IDF_2):] # trim out idf
70+
# https://wiki.python.org/moin/Python3UnicodeDecodeError
71+
# seems like the bytes created by pyaes are best decrypted using it
72+
enc = base64.urlsafe_b64decode(enc).decode('iso-8859-1')
73+
# decode string
74+
aes = AESModeOfOperationCTR(key_32(key))
75+
st = aes.decrypt(enc)
76+
st = st.decode('utf8') # because utf8 is what everyone uses
77+
# ^^ decode error might be returned even when password is wrong
78+
# check if correctly decoded
79+
if not st.endswith(EXTRA_STR_2):
80+
return None
81+
else:
82+
return st[:-1 * len(EXTRA_STR_2)]
83+
84+
4785
def get_file_list():
4886
listFiles = []
4987
sts = Settings()
@@ -71,11 +109,15 @@ def update_file(funcptr, flist, key):
71109
data = fptr.read()
72110
fptr.close()
73111
fptr = open(file, 'w')
74-
newData = funcptr(key, data)
112+
try:
113+
newData = funcptr(key, data)
114+
except Exception:
115+
print_exc()
116+
newData = None # handled sufficiently well now
75117
if newData is None:
76118
newData = data
77119
failed = True
78-
print_err('Failed decrypting %s' % file)
120+
print_err('Failed processing %s' % file)
79121
fptr.write(newData)
80122
fptr.close()
81123
# check if failed
@@ -89,3 +131,11 @@ def get_key():
89131
while key == '':
90132
key = getpass('Enter key > ')
91133
return key
134+
135+
136+
def key_32(key):
137+
if len(key) > 32:
138+
key = key[:32]
139+
else:
140+
key = key + ('0' * (32 - len(key)))
141+
return bytes(key, 'utf8')

sublime_notebook/pyaes/__init__.py

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
# The MIT License (MIT)
2+
#
3+
# Copyright (c) 2014 Richard Moore
4+
#
5+
# Permission is hereby granted, free of charge, to any person obtaining a copy
6+
# of this software and associated documentation files (the "Software"), to deal
7+
# in the Software without restriction, including without limitation the rights
8+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
# copies of the Software, and to permit persons to whom the Software is
10+
# furnished to do so, subject to the following conditions:
11+
#
12+
# The above copyright notice and this permission notice shall be included in
13+
# all copies or substantial portions of the Software.
14+
#
15+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21+
# THE SOFTWARE.
22+
23+
# This is a pure-Python implementation of the AES algorithm and AES common
24+
# modes of operation.
25+
26+
# See: https://en.wikipedia.org/wiki/Advanced_Encryption_Standard
27+
# See: https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation
28+
29+
30+
# Supported key sizes:
31+
# 128-bit
32+
# 192-bit
33+
# 256-bit
34+
35+
36+
# Supported modes of operation:
37+
# ECB - Electronic Codebook
38+
# CBC - Cipher-Block Chaining
39+
# CFB - Cipher Feedback
40+
# OFB - Output Feedback
41+
# CTR - Counter
42+
43+
# See the README.md for API details and general information.
44+
45+
# Also useful, PyCrypto, a crypto library implemented in C with Python bindings:
46+
# https://www.dlitz.net/software/pycrypto/
47+
48+
49+
VERSION = [1, 3, 0]
50+
51+
from .aes import AES, AESModeOfOperationCTR, AESModeOfOperationCBC, AESModeOfOperationCFB, AESModeOfOperationECB, AESModeOfOperationOFB, AESModesOfOperation, Counter
52+
from .blockfeeder import decrypt_stream, Decrypter, encrypt_stream, Encrypter
53+
from .blockfeeder import PADDING_NONE, PADDING_DEFAULT

0 commit comments

Comments
 (0)