forked from shadowhand/git-encrypt
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgitcrypt
executable file
·175 lines (148 loc) · 3.57 KB
/
gitcrypt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
#!/bin/bash
readonly VERSION="0.3.0"
readonly DEFAULT_CIPHER="aes-256-ecb"
[ -z "$GIT_DIR" ] && GIT_DIR=".git"
init_config() {
local answer
if [ ! -d "$GIT_DIR" ]; then
echo "Directory is not a git repository. Did you forget to run 'git init'?"
return 1
fi
while [ 1 ]; do
while [ -z "$SALT" ]; do
echo -n "Generate a random salt? [Y/n] "
read answer
case "$answer" in
n*|N*)
echo -n "Shared salt as hex characters: "
read SALT
if [ $(echo "$SALT" | grep '[^a-f0-9]' | wc -l) -ne 0 ]; then
echo "Error: non-hex characters in salt"
unset -v SALT
fi
;;
*)
local md5=$(which md5 2>/dev/null || which md5sum 2>/dev/null)
SALT=$(head -c 10 < /dev/random | $md5 | cut -c-16)
;;
esac
done
while [ -z "$PASS" ]; do
echo -n "Generate a random password? [Y/n]"
read answer
case "$answer" in
n*|N*)
echo -n "Enter your passphrase: "
read PASS
;;
*)
PASS=$(cat /dev/urandom | LC_ALL="C" tr -dc '!@#$%^&*()_A-Z-a-z-0-9' | head -c32)
;;
esac
done
while [ 1 ]; do
echo -n "What encryption cipher do you want to use? [$DEFAULT_CIPHER] "
read CIPHER
[ -z "$CIPHER" ] && CIPHER="$DEFAULT_CIPHER"
local exists
exists=$(openssl list-cipher-commands | grep "$CIPHER")
[ $? -eq 0 ] && break
echo "Error: Cipher '$CIPHER' is not available"
done
echo -e "\nThis configuration will be stored:\n"
echo "salt: $SALT"
echo "pass: $PASS"
echo "cipher: $CIPHER"
echo -e -n "\nDoes this look right? [Y/n] "
read answer
case "$answer" in
n*|N*)
# Reconfigure
unset -v SALT
unset -v PASS
unset -v CIPHER
;;
*)
# Finished
break
;;
esac
done
echo -n "Do you want to use $GIT_DIR/info/attributes? [Y/n] "
read answer
local attrs
case "$answer" in
n*|N*)
attrs=".gitattributes"
;;
*)
attrs="$GIT_DIR/info/attributes"
;;
esac
local pattern
echo -n "What files do you want encrypted? [*] "
read pattern
[ -z "$pattern" ] && pattern="*"
echo "$pattern filter=encrypt diff=encrypt" >> $attrs
echo "[merge]" >> $attrs
echo " renormalize=true" >> $attrs
# Encryption
git config gitcrypt.salt "$SALT"
git config gitcrypt.pass "$PASS"
git config gitcrypt.cipher "$CIPHER"
# Filters
git config filter.encrypt.smudge "gitcrypt smudge"
git config filter.encrypt.clean "gitcrypt clean"
git config diff.encrypt.textconv "gitcrypt diff"
}
_clean() {
# Encrypt using OpenSSL
openssl enc -base64 -$CIPHER -S "$SALT" -k "$PASS"
}
_smudge() {
# If decryption fails, use `cat` instead
openssl enc -d -base64 -$CIPHER -k "$PASS" 2> /dev/null || cat
}
_diff() {
# If decryption fails, use `cat` instead
openssl enc -d -base64 -$CIPHER -k "$PASS" -in "$1" 2> /dev/null || cat "$1"
}
case "$1" in
clean|smudge|diff)
# Need a shared salt
SALT=$(git config gitcrypt.salt)
if [ -z "$SALT" ]; then
echo "Gitcrypt: shared salt (gitcrypt.salt) has not been configured"
exit 1
fi
# Need a secure passphrase
PASS=$(git config gitcrypt.pass)
if [ -z "$PASS" ]; then
echo "Gitcrypt: secure passphrase (gitcrypt.pass) has not been configured"
exit 1
fi
# And a cipher mode
CIPHER=$(git config gitcrypt.cipher)
[ -z "$CIPHER" ] && CIPHER="$DEFAULT_CIPHER"
# Execute command
_$1 "$2"
;;
init)
# Run setup commands
init_config
;;
version)
# Show version
echo "gitcrypt version $VERSION"
;;
*)
# Not a valid option
if [ -z "$1" ]; then
echo "Gitcrypt: available options: init, version"
else
echo "Gitcrypt: command does not exist: $1"
fi
exit 1
;;
esac
exit 0