I sent a link to Yaron Minsky’s article OCaml for the Masses to some long time buddies of mine and one of them said that there aren’t enough OCaml systems administration programming examples.

He sent me some Python code that produces a string given a hash found in Cisco IOS configurations. I wrote an OCaml version along with a function to produce a hash from a string.

This uses Jane Street’s Core library which has a lot of nifty features so be sure to download and install that.

Here you go Robert:

!/your-path-here/ocaml

open Core.Std

let xlat = [| 0x64; 0x73; 0x66; 0x64; 0x3b; 0x6b; 0x66; 0x6f;
             0x41; 0x2c; 0x2e; 0x69; 0x79; 0x65; 0x77; 0x72;
             0x6b; 0x6c; 0x64; 0x4a; 0x4b; 0x44; 0x48; 0x53;
             0x55; 0x42; 0x73; 0x67; 0x76; 0x63; 0x61; 0x36;
             0x39; 0x38; 0x33; 0x34; 0x6e; 0x63; 0x78; 0x76;
             0x39; 0x38; 0x37; 0x33; 0x32; 0x35; 0x34; 0x6b;
             0x3b; 0x66; 0x67; 0x38; 0x37 |]

let get_pairs hash =
  List.rev
    (Array.fold ~init:[]
      ~f:(fun acc x -> match x with |[|x|]->x::acc |_->failwith "Bad hash")
     (Pcre.extract_all ~full_match:false ~pat:"(..)" hash))

let hash7 hash =
  let xlater s c =
    Char.to_string (Char.of_int_exn ((Int.of_string ("0x"^c) lxor xlat.(s))))
  in
  match get_pairs hash with
  | salt::rest ->
      let (result,_) =
        List.fold
          ~init:("",Int.of_string(salt))
          ~f:(fun (result,s) c -> (result ^ (xlater s c), s + 1))
          rest
      in
      result
  | _ -> failwith "Mangled hash"

let () =
  printf "%sn" (hash7 "03365409031D350C4B080D165705041E093965")

Here is the python version:

!/usr/bin/python

import re

Decode bogus Cisco hash

def hash7(hash):
  xlat = [0x64, 0x73, 0x66, 0x64, 0x3b, 0x6b, 0x66, 0x6f,
           0x41, 0x2c, 0x2e, 0x69, 0x79, 0x65, 0x77, 0x72,
           0x6b, 0x6c, 0x64, 0x4a, 0x4b, 0x44, 0x48, 0x53,
           0x55, 0x42, 0x73, 0x67, 0x76, 0x63, 0x61, 0x36,
           0x39, 0x38, 0x33, 0x34, 0x6e, 0x63, 0x78, 0x76,
           0x39, 0x38, 0x37, 0x33, 0x32, 0x35, 0x34, 0x6b,
           0x3b, 0x66, 0x67, 0x38, 0x37 ];
  if (len(hash)&1 == 1):
    return None # Odd length of hash
  m = re.search('^(..)(.+)', hash)
  if m:
    (s, e) = (int(m.group(1)), m.group(2))
  else:
    return None
  result = ''
  for c in re.findall('[da-fA-F]{2}', e):
    result = result + ("%c" % (int(c, 16) ^ xlat[s]))
    s = s + 1
  return result

hash = a = raw_input('Enter Hash: ')
print "%s" % hash7(hash)