/usr/lib/python2.7/dist-packages/otrapps/otr_private_key.py is in keysync 0.2.2-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
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 | #!/usr/bin/env python
# -*- coding: utf-8 -*-
'''a module for reading and writing libotr's secret key data'''
from __future__ import print_function
from pyparsing import Forward, Group, OneOrMore, Optional, ParseFatalException, \
Suppress, Word, ZeroOrMore, alphanums, dblQuotedString, hexnums, nums, \
printables, removeQuotes
from base64 import b64decode
import sys
if __name__ == '__main__':
sys.path.insert(0, "../") # so the main() test suite can find otrapps module
import otrapps.util
class OtrPrivateKeys():
@staticmethod
def verifyLen(t):
t = t[0]
if t.len is not None:
t1len = len(t[1])
if t1len != t.len:
raise ParseFatalException, \
"invalid data of length %d, expected %s" % (t1len, t.len)
return t[1]
@staticmethod
def parse_sexp(data):
'''parse sexp/S-expression format and return a python list'''
# define punctuation literals
LPAR, RPAR, LBRK, RBRK, LBRC, RBRC, VBAR = map(Suppress, "()[]{}|")
decimal = Word("123456789", nums).setParseAction(lambda t: int(t[0]))
bytes = Word(printables)
raw = Group(decimal.setResultsName("len") + Suppress(":") + bytes).setParseAction(OtrPrivateKeys.verifyLen)
token = Word(alphanums + "-./_:*+=")
base64_ = Group(Optional(decimal, default=None).setResultsName("len") + VBAR
+ OneOrMore(Word( alphanums +"+/=" )).setParseAction(lambda t: b64decode("".join(t)))
+ VBAR).setParseAction(OtrPrivateKeys.verifyLen)
hexadecimal = ("#" + OneOrMore(Word(hexnums)) + "#")\
.setParseAction(lambda t: int("".join(t[1:-1]),16))
qString = Group(Optional(decimal, default=None).setResultsName("len") +
dblQuotedString.setParseAction(removeQuotes)).setParseAction(OtrPrivateKeys.verifyLen)
simpleString = raw | token | base64_ | hexadecimal | qString
display = LBRK + simpleString + RBRK
string_ = Optional(display) + simpleString
sexp = Forward()
sexpList = Group(LPAR + ZeroOrMore(sexp) + RPAR)
sexp << ( string_ | sexpList )
try:
sexpr = sexp.parseString(data)
return sexpr.asList()[0][1:]
except ParseFatalException, pfe:
print("Error:", pfe.msg)
print(pfe.loc)
print(pfe.markInputline())
@staticmethod
def parse(filename):
'''parse the otr.private_key S-Expression and return an OTR dict'''
f = open(filename, 'r')
data = ""
for line in f.readlines():
data += line
f.close()
sexplist = OtrPrivateKeys.parse_sexp(data)
keydict = dict()
for sexpkey in sexplist:
if sexpkey[0] == "account":
key = dict()
name = ''
for element in sexpkey:
# 'name' must be the first element in the sexp or BOOM!
if element[0] == "name":
if element[1].find('/') > -1:
name, resource = element[1].split('/')
else:
name = element[1].strip()
resource = ''
key = dict()
key['name'] = name.strip()
key['resource'] = resource.strip()
if element[0] == "protocol":
key['protocol'] = element[1]
elif element[0] == "private-key":
if element[1][0] == 'dsa':
key['type'] = 'dsa'
for num in element[1][1:6]:
key[num[0]] = num[1]
keytuple = (key['y'], key['g'], key['p'], key['q'])
key['fingerprint'] = otrapps.util.fingerprint(keytuple)
keydict[name] = key
return keydict
@staticmethod
def _getaccountname(key, resources):
if resources:
# pidgin requires the XMPP Resource in the account name for otr.private_keys
if key['protocol'] == 'prpl-jabber' and 'x' in key.keys():
name = key['name']
if name in resources.keys():
return key['name'] + '/' + resources[name]
else:
return key['name'] + '/' + 'ReplaceMeWithActualXMPPResource'
return key['name']
@staticmethod
def write(keydict, filename, resources=None):
privkeys = '(privkeys\n'
for name, key in keydict.items():
if 'x' in key:
dsa = ' (p #' + ('%0258X' % key['p']) + '#)\n'
dsa += ' (q #' + ('%042X' % key['q']) + '#)\n'
dsa += ' (g #' + ('%0258X' % key['g']) + '#)\n'
dsa += ' (y #' + ('%0256X' % key['y']) + '#)\n'
dsa += ' (x #' + ('%042X' % key['x']) + '#)\n'
account = OtrPrivateKeys._getaccountname(key, resources)
contents = ('(name "' + account + '")\n' +
'(protocol ' + key['protocol'] + ')\n' +
'(private-key \n (dsa \n' + dsa + ' )\n )\n')
privkeys += ' (account\n' + contents + ' )\n'
privkeys += ')\n'
f = open(filename, 'w')
f.write(privkeys)
f.close()
if __name__ == "__main__":
import sys
import pprint
pp = pprint.PrettyPrinter(indent=4)
pp.pprint(OtrPrivateKeys.parse(sys.argv[1]))
|