nanog mailing list archives

Re: MD5 is insecure


From: Tom Beecher via NANOG <nanog () lists nanog org>
Date: Wed, 3 Sep 2025 09:39:34 -0400

Brent-

Yes, IOS is storing the MD5 of the binary key data, not the base64 version.
I had that wrong. Still a distinction without a difference. The preimage
problem still exists.

And as you've been clearly ramping up the condescension in the last few
messages, I don't feel inclined to debate this with you any further.  Take
care.

On Wed, Sep 3, 2025 at 7:58 AM brent saner <brent.saner () gmail com> wrote:

On Wed, Sep 3, 2025 at 2:00 AM Tom Beecher <beecher () beecher cc> wrote:

Brent-

Yes, you are correct about what is transmitted over the wire. Thank you.
That being said, I believe it's still a distinction without a difference.

The only information stored on the router is the MD5 hash *of the base64
encoded public key*. Therefore when someone attempts to authenticate, the
router *must* convert the presented mpint to base64, then take the md5sum
of the result and compare to the config.


No, Tom; still wrong. See Dan Mahoney's Medium post
<https://gushi.medium.com/what-i-learned-from-configuring-ssh-pubkey-auth-on-cisco-ios-cbeb1e5b3b77>
.

He uploads the key:

switch(config)#username testcase privilege 15
switch(config)#ip ssh pubkey-chain
switch(conf-ssh-pubkey)#username testcase
switch(conf-ssh-pubkey-user)#key-string
switch(conf-ssh-pubkey-data)#AAAAB3NzaC1yc2EAAAADAQABAAABgQDW
switch(conf-ssh-pubkey-data)#45rLjxwnPeaZtu5h4PzvFaLqLIb1ozO+BAdDwqIY
switch(conf-ssh-pubkey-data)#bbnqFnbhD42wZ6Cx2iQ3UKet4PziupgXLm2Yc69Q
switch(conf-ssh-pubkey-data)#3HE6hP2Z23qHhemZG1G7O9liZ/+P40s2QLm2iRIm
switch(conf-ssh-pubkey-data)#TZ4vsKoHNo51aQw+ZI+vUc+nKbZLFOzdZHuqhrw2
switch(conf-ssh-pubkey-data)#oG209csH3rVcBS3ItZuN2MP9+86Lr+64z4ls0Cqq
switch(conf-ssh-pubkey-data)#MpBTZlgnxGtLfLW8ASASJm5Fh9onm60O2enBXsrP
switch(conf-ssh-pubkey-data)#vC5ZKaLu0tecPC8hFwE7Bi7hAhpxzq1m8V3rdFlo
switch(conf-ssh-pubkey-data)#8F05FXs1U89Ou4kgImAdwuW4YTUF15rfUSXR+hpM
switch(conf-ssh-pubkey-data)#0c+HAf1KVLE+484zh00CJw1pvxLXTumacfjM0hdJ
switch(conf-ssh-pubkey-data)#sRRoSru325hjKu+zhjUVlI20qt+K7Eb+qV62mDUn
switch(conf-ssh-pubkey-data)#bsvIGfvFVAD0vCOqi3pASDxrrcGUHEU0zMAP8+mG
switch(conf-ssh-pubkey-data)#6Ai7NZ+ilQs31NZcECubNDXh8xESyQI7w/r8xd5H
switch(conf-ssh-pubkey-data)#CBfLE5VdssqZxflw832RQllS5p+d8sU=
switch(conf-ssh-pubkey-data)#exit
switch(conf-ssh-pubkey-user)#exit
switch(conf-ssh-pubkey)#exit


We can just copy and paste this right into a text file *t.txt* to prove
this.

So everyone at home can play along:

$ file t.txt
t.txt: ASCII text

$ head -n1 t.txt
switch(config)#username testcase privilege 15


$ b3sum t.txt
b2caccb61dfd0d8bab4f864befbe6bc62d6bf376e44db2d118dd2e8e3589d6df  t.txt


$ head -n1 t.txt | xxd
00000000: 7377 6974 6368 2863 6f6e 6669 6729 2375  switch(config)#u
00000010: 7365 726e 616d 6520 7465 7374 6361 7365  sername testcase
00000020: 2070 7269 7669 6c65 6765 2031 350a        privilege 15.


$ tail -n1 t.txt | xxd
00000000: 7377 6974 6368 2863 6f6e 662d 7373 682d  switch(conf-ssh-
00000010: 7075 626b 6579 2923 6578 6974 0a         pubkey)#exit.


No extra trailing whitespace, pasted just as-is, nothing up my sleeve.

First let's remove the prompt prefixes since those obviously wouldn't be
present in the actual uploaded form.

$ sed -i -re 's/^.+#//g' t.txt


You should now have:

$ cat t.txt
username testcase privilege 15
ip ssh pubkey-chain
username testcase
key-string
AAAAB3NzaC1yc2EAAAADAQABAAABgQDW
45rLjxwnPeaZtu5h4PzvFaLqLIb1ozO+BAdDwqIY
bbnqFnbhD42wZ6Cx2iQ3UKet4PziupgXLm2Yc69Q
3HE6hP2Z23qHhemZG1G7O9liZ/+P40s2QLm2iRIm
TZ4vsKoHNo51aQw+ZI+vUc+nKbZLFOzdZHuqhrw2
oG209csH3rVcBS3ItZuN2MP9+86Lr+64z4ls0Cqq
MpBTZlgnxGtLfLW8ASASJm5Fh9onm60O2enBXsrP
vC5ZKaLu0tecPC8hFwE7Bi7hAhpxzq1m8V3rdFlo
8F05FXs1U89Ou4kgImAdwuW4YTUF15rfUSXR+hpM
0c+HAf1KVLE+484zh00CJw1pvxLXTumacfjM0hdJ
sRRoSru325hjKu+zhjUVlI20qt+K7Eb+qV62mDUn
bsvIGfvFVAD0vCOqi3pASDxrrcGUHEU0zMAP8+mG
6Ai7NZ+ilQs31NZcECubNDXh8xESyQI7w/r8xd5H
CBfLE5VdssqZxflw832RQllS5p+d8sU=
exit
exit
exit


Let's of course get rid of the commands as well. Those aren't part of the
base64 of the key.

$ sed -i -e '19,21d' -e '1,4d' t.txt


$ cat t.txt
AAAAB3NzaC1yc2EAAAADAQABAAABgQDW
45rLjxwnPeaZtu5h4PzvFaLqLIb1ozO+BAdDwqIY
bbnqFnbhD42wZ6Cx2iQ3UKet4PziupgXLm2Yc69Q
3HE6hP2Z23qHhemZG1G7O9liZ/+P40s2QLm2iRIm
TZ4vsKoHNo51aQw+ZI+vUc+nKbZLFOzdZHuqhrw2
oG209csH3rVcBS3ItZuN2MP9+86Lr+64z4ls0Cqq
MpBTZlgnxGtLfLW8ASASJm5Fh9onm60O2enBXsrP
vC5ZKaLu0tecPC8hFwE7Bi7hAhpxzq1m8V3rdFlo
8F05FXs1U89Ou4kgImAdwuW4YTUF15rfUSXR+hpM
0c+HAf1KVLE+484zh00CJw1pvxLXTumacfjM0hdJ
sRRoSru325hjKu+zhjUVlI20qt+K7Eb+qV62mDUn
bsvIGfvFVAD0vCOqi3pASDxrrcGUHEU0zMAP8+mG
6Ai7NZ+ilQs31NZcECubNDXh8xESyQI7w/r8xd5H
CBfLE5VdssqZxflw832RQllS5p+d8sU=


Say, there we go! That's looking VERY base64-y! Now, we're looking for the
MD5 sum *270C78AD8FB00FD98FEDF00C0E8F4D35* (or
*270c78ad8fb00fd98fedf00c0e8f4d35,* same thing; hashes are binary,
they're just usually represented in hex because it's a lot easier for human
eyes than a lot of 0's and 1's).

ip ssh pubkey-chain
 username testcase
  key-hash ssh-rsa 270C78AD8FB00FD98FEDF00C0E8F4D35
 quit

Let's make a standard GNU md5sum check file format.

$ cat t.md5
270c78ad8fb00fd98fedf00c0e8f4d35  t.txt


Ok! Let's check for that MD5!

$ md5sum t.txt
ea327a2f162f4ba8d6a9f1fff6f7cc0e  t.txt


Wow... That's really, really weird, Tom. You keep saying it stores the MD5
of the *base64 encoding* of the key, but that's a totally different
checksum.
Well, maybe it strips the newlines?

$ cat t.txt | tr -d '\n' | md5sum
bf91a39b8ff4ce69850dcd945f1319d5  -

$ cat t.txt | tr -d '\n' > t.stripped ; mv t.stripped t.txt
$ md5sum -c t.md5
t.txt: FAILED
md5sum: WARNING: 1 computed checksum did NOT match


Huh. No dice, Tom.

Hey, you don't suppose it maybe... decodes the base64, and *stores the
MD5 checksum of what the pubkey would look like on the wire*?

(Sidenote, base64(1) is newline-agnostic when decoding; *cat t.txt | tr
-d '\n' | base64 -d | b3sum* will return the same exact sum as *cat t.txt
| base64 -d | b3sum*. Still no funny business, promise!)

$ cat t.txt | base64 -d | md5sum
270c78ad8fb00fd98fedf00c0e8f4d35  -

$ cat t.txt | base64 -d > t.bin ; mv t.bin t.txt
$ md5sum -c t.md5
t.txt: OK


Holy cats, Tom! Would ya look at that? It looks like it's *storing the
MD5 sum of the actual real public key*, not the base64 encoded version!
Who could have ever possibly guessed such a thing?

$ cat t.txt | head -c 15 | xxd
00000000: 0000 0007 7373 682d 7273 6100 0000 03    ....ssh-rsa....


]$ cat t.txt | head -c 15 | xxd -ps -c 0
000000077373682d72736100000003


Crazy! That DEFINITELY looks like the straight byte-packed over-the-wire
form <https://sshref.dev/#bkdn_rsa_pub_struct>!
Man, that's really weird, Tom. It's almost as if *IOS would what to keep
the checksum of the actual bytes it'd be checking it against*, rather
than *a base64-encoded version of the data it'd be checking it against*,
so it wouldn't have to *base64-encode the bytes every time* they were
sent during session establishment.

_______________________________________________
NANOG mailing list 
https://lists.nanog.org/archives/list/nanog () lists nanog org/message/XI6GII774JEJZJPYN3NTZJEE5RR3SVUZ/

Current thread: