digest-response.py 3.8 KB
Newer Older
1 2 3
#!/usr/bin/env python

############################################################################
4
# digest-response.py
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
# Copyright (C) 2015  Belledonne Communications, Grenoble France
#
############################################################################
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
21
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
22 23 24 25 26 27 28 29 30 31 32
#
############################################################################

import hashlib
import sys

import argparse
def int16(x):
	return int(x, 16)
	
def main(argv=None):
33 34 35 36
	parser = argparse.ArgumentParser(description='Compute response parameter for a digest authetication. ex %(prog)s --qop-auth --cnonce f1b8598a --nonce-count 2b --userid toto --realm sip.linphone.org --password secret REGISTER sip:sip.linphone.org QPUC2gAAAABufvQmAABDq5AKuv4AAAAA')
	parser.add_argument('--userid',help='User identifier')
	parser.add_argument('--realm',help='realm as defined by the server in 401/407')
	parser.add_argument('--password',help='clear text password')
37 38 39 40
	parser.add_argument('method',help='sip method of the challanged request line')
	parser.add_argument('uri',help='sip uri of the challanged request uri')
	parser.add_argument('nonce',help='Nonce param as defined by the server in 401/407')
	
41
	parser.add_argument('--ha1',help='ha1 MD5(username:realm:password)')
42
	parser.add_argument('--qop-auth', help='Indicate if auth mode has to reuse nonce (I.E qop=auth',action='store_true')
43
        
44
	parser.add_argument('--cnonce', help='client nonce')
45 46
	parser.add_argument('--nonce-count',type=int16, help='nonce count in hexa: ex 2b')
	parser.add_argument('--algorithm', help='choose algorithm from MD5 and SHA256')
47 48 49 50
					
	
	args = parser.parse_args(argv)

51
	if not args.ha1 :
52 53 54 55 56 57
        	if not args.algorithm:
            		#HA1=MD5(username:realm:password)
            		ha1 = hashlib.md5()
		else:
			#HA1=SHA256(username:realm:password)
			ha1 = hashlib.sha256()
58 59 60 61
		ha1.update((args.userid+":"+args.realm+":"+args.password).encode())
		ha1_value = ha1.hexdigest()
	else:
		ha1_value = args.ha1
62

63 64 65 66 67 68 69
	if not args.algorithm:
		#HA2=MD5(method:digestURI)
		ha2 = hashlib.md5()
	else:
		#HA2=SHA256(method:digestURI)
		ha2 = hashlib.sha256()
	
70
	ha2.update((args.method+":"+args.uri).encode())
71
	print ("ha1 = "+ha1_value);
72 73 74 75 76 77 78
	print ("ha2 = "+ha2.hexdigest());		
	
	if args.qop_auth :
		if not args.cnonce and not args.nonce_count :
			print ("--qop-auth requires both --cnonce and --nonce-count")
			sys.exit(-1)
		
79 80 81 82 83 84 85
		if not args.algorithm:
			#response=MD5(HA1:nonce:nonceCount:clientNonce:qop:HA2)
			response = hashlib.md5()
		else:
			#response=SHA256(HA1:nonce:nonceCount:clientNonce:qop:HA2)
			response = hashlib.sha256()
        
86
		response.update(		(ha1_value
87 88 89 90 91 92 93 94 95
							+":"+args.nonce
							+":" + '{:08x}'.format(args.nonce_count)
							+":" + args.cnonce
							+":auth"
							+":" + ha2.hexdigest()).encode())
		print ("responce = "+response.hexdigest());	
				
	
	else:
96 97 98 99 100 101 102
		if not args.algorithm:
			#response=MD5(HA1:nonce:HA2)
			response = hashlib.md5()
		else:
			#response=SHA256(HA1:nonce:HA2)
			response = hashlib.sha256()
		
103
		response.update((ha1_value+":"+args.nonce+":"+ha2.hexdigest()).encode())
104 105 106 107 108 109 110 111 112 113 114
		print ("responce = "+response.hexdigest());	
			
		



if __name__ == "__main__":
	sys.exit(main())