Skip to content

Instantly share code, notes, and snippets.

@JamesTheAwesomeDude
Last active December 1, 2023 15:56
Show Gist options
  • Save JamesTheAwesomeDude/b6705e09d99aaa7cec13c9e789a82015 to your computer and use it in GitHub Desktop.
Save JamesTheAwesomeDude/b6705e09d99aaa7cec13c9e789a82015 to your computer and use it in GitHub Desktop.
Free OID Generator
#!/usr/bin/env python3
"""DEC Sixbit bijective hierarchicial mapping
of the DNS namespace onto hereby-proposed child arc dns-root(52)
of IANA's unused OID {iso(1) identified-organization(3) iana(90)}
NOTE that this is a horrific hack I made as a joke / proof-of-concept / demo.
There are several legitimate alternatives you could consider, h/t http://oid-info.com/faq.htm#10
1. IANA gives OIDs out for free, both to natural persons and to organizations,
of any nationality,
under {iso(1) identified-organization(3) dod(6) internet(1) private(4) enterprise(1)}
https://www.iana.org/assignments/enterprise-numbers/
2. THIS ARC IS ACTUALLY SUPPOSED TO BE USED FOR DOCUMENTATION PURPOSES:
{joint-iso-itu-t(2) example(999)}
3. If you need an OID in connection with institutional research, work for an employer,
or even just a large open-source project, PLEASE check to see if that organization
already has an arc they'd like you to use for your current project!
4. There are a handful of organizations other than IANA which reportedly hand out OIDs
entirely free of charge:
i. The European Telecommunications Standards Institute, apparently, will assign
children of {itu-t(0) identified-organization(4) etsi(0)}
to "any organization" that requests them.
https://portal.etsi.org/pnns/oidlist#Reserved_Domain
ii. ViaSoft gives out free child OIDs within their own PEN arc, if that floats your goat.
They strongly urge you to think thrice whether their service is appropriate
for your use-case, however, given the abundance of other options.
It looks like small open-source and shareware projects are who they're aiming at serving.
https://oidplus.viathinksoft.com/oidplus/?goto=oidplus%3Acom.viathinksoft.freeoid
iii. Microsoft seemingly has an offline self-serve hybrid-GUID system that slaps what appears to be
a truncated hash of your system's original NIC's MAC address underneath an OID arc they manage.
They only suggest its use for Windows Server- and Active Directory-related use cases.
https://learn.microsoft.com/en-us/windows/win32/ad/obtaining-an-object-identifier-from-microsoft
5. Many countries have a National Registry that is IN PRINCIPLE available
to organizations with a primary business presence in the country and
sometimes even the general citizenry. However, most of these are either
hideously expensive or poorly maintained. A few representative examples:
- ANSI sells entries in {joint-iso-itu-t(2) country(16) us(840)}
for a grand or two. (That's around 6 months' median global wages!
All "cost recovery", of course -- the U.S. is a beacon of efficiency...)
It appears not to permit personal registrations.
https://www.ansi.org/about/roles/registration-program/organization-names
- Iceland's Post and Telecom Administration filed a statement alleging they'd
maintain registration services, but the service isn't anywhere on their website.
Apparently exactly one (1) company so far has figured out the process for registering an Icelandic national OID.
Maybe you have to send them an e-mail or something?
https://www.fjarskiptastofa.is/fjarskiptastofa/tolfraedi-og-gagnasafn/rafraenar-umsoknir-og-tilkynningar/tengilidaupplysingar-fyrir-netoryggissveitina-cert-is/
- Organizations with enough business presence in Russia to have a TIN
have the option to get an OID assigned for what appears to be no charge,
through online registration via a web portal they've set up.
https://oid.iitrust.ru/faq/detail.php?ID=80
- Japan: Mail a completed copy of "form 2" below in to the Ministry of Internal Affairs and Communications.
I'm not too keen with Google Translate, but I didn't see anything in there
specifying that ONLY Japanese citizens can apply... No fee schedule that I could see listed, either.
https://www.soumu.go.jp/main_sosiki/joho_tsusin/hyojun/pdf/object02.pdf#page=7
6. You're technically allowed to pick random 128-bit integers and claim them as your own
underneath {joint-iso-itu-t(2) uuid(25)}
However, this is a crippling option as many X.509 certificate signers have length limits that
preclude these, which may or may not be related to much Microsoft software which also can't handle this.
If you go this route, everyone will make fun of you.
"""
import codecs
from functools import reduce as _reduce
from itertools import starmap as _starmap, chain as _chain, repeat as _repeat
from operator import eq as _eq
IANA = (1, 3, 90) # https://www.iana.org/domains/root
DEC6 = bytes(range(32, 96)).decode('ascii') # http://rabbit.eng.miami.edu/info/decchars.html
_ALTNICS = {
'opennic.org': {'bbs', 'chan', 'cyb', 'dyn', 'epic', 'fur', 'geek', 'gopher', 'indy', 'libre', 'neo', 'null', 'o', 'oss', 'oz', 'parody', 'pirate'},
'emercoin.com': {'bazar', 'coin', 'emc', 'lib'},
'ens.domains': {'eth'},
'namecoin.org': {'bit'},
'chn996.cn': {'chn'},
'yeti-dns.org': set(), # included so I don't forget they exist despite the fact they're not deploying any alt-TLDs
'52.rkn.gov.ru': set(), # likewise
'handshake.org': set(), # ...
}
ALTNICS = dict((tuple(reversed(tld.upper().split('.'))), tuple(reversed(sponsor.upper().split('.')))) for sponsor, tlds in _ALTNICS.items() for tld in tlds)
def domain2oid(domain: str, base=IANA, subnodes=((52,), (0,)), altnics=ALTNICS) -> str:
"""Given DNS domain `domain`, return its "corresponding" OID"""
parts = domain.encode('idna').decode('ascii') # Replace unencodables with IDNA
parts = tuple(map(str.upper, reversed(parts.split('.')))) # Convert to upper-case tuple
oid = _domain2oid(parts, base, subnodes, altnics) # Convert to OID
return '.'.join(str(segment) for segment in oid) # Return a string
def _domain2oid(parts, base=(), subnodes=((),), altnics={}):
payload = base + subnodes[0]
for altroot, sponsor in altnics.items():
if _istartswith(parts, altroot):
sponsor_base = tuple(map(crunch, sponsor))
payload += _domain2oid(parts=(), base=sponsor_base, subnodes=subnodes[1:])
break
payload += tuple(map(crunch, parts))
return payload
def oid2domain(oid, base=IANA, subnodes=((52,), (0,)), altnics=ALTNICS, decode_idna=False):
"""Inverse of `domain2oid`"""
if isinstance(oid, str):
# Function allows "1.2.3.4" and (1, 2, 3, 4), for convenience
oid = tuple(int(i or 0) for i in oid.split('.'))
domain = _oid2domain(oid, base, subnodes, altnics) # Convert to domain
domain = '.'.join(map(str.lower, reversed(domain))) # Convert from upper-case tuple
if decode_idna:
domain = domain.encode('ascii').decode('idna') # Decode from IDNA
return domain
def _oid2domain(oid, base=(), subnodes=((),), altnics={}):
prefix = base + subnodes[0]
if not _istartswith(oid, prefix):
oid_printable = '.'.join(map(str, oid))
prefix_printable = '.'.join(map(str, prefix))
raise ValueError("%s isn't under %s" % (oid_printable, prefix_printable))
oid_domain = oid[len(prefix):]
for altroot, sponsor in altnics.items():
sponsor_base = tuple(map(crunch, sponsor))
sponsor_oid_fragment = _domain2oid(parts=(), base=sponsor_base, subnodes=subnodes[1:])
if _istartswith(oid_domain, sponsor_oid_fragment):
oid_domain = oid_domain[len(sponsor_oid_fragment):]
break
parts = tuple(map(uncrunch, oid_domain))
return parts
def crunch(s: str) -> int:
"""Bijectively pack a string into a single integer as DEC SIXBIT"""
m = 2**6
result = 0
for c in map(DEC6.index, s):
result *= m
result += (c+1)
return result
def uncrunch(i: int) -> str:
"""Unpack an integer as a DEC SIXBIT bijectively-packed string; inverse of `crunch`"""
m = 2**6
i = int(i)
result = []
while i:
i -= 1
i, c = divmod(i, m)
result.append(DEC6[c])
return str().join(reversed(result))
def _istartswith(a, b):
return all(_starmap(_eq, zip(_chain(a, _starmap(object, _repeat(()))), b)))
if __name__ == '__main__':
import sys
args = sys.argv[1:]
if not args:
# No arguments; run interactively
args.append(input("Enter a domain name:\n> "))
# Output in TSV format
print(" domain name ", "OID", sep="\t")
for arg in args:
if not all(all(map(str.isdigit, part)) for part in arg.split('.')):
print(arg, domain2oid(arg), sep="\t")
else:
print(oid2domain(arg), arg, sep="\t")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment