part of #275
We'll need a way to construct WKD URLs with an email address as an input. Signature:
classWkd{staticfunconstructUrl(email: string,mode: ADVANCED|DIRECT): string}This will follow the following spec: https://tools.ietf.org/html/draft-koch-openpgp-webkey-service-11 - this uses z-base-32 which is different from base-32, and may need to be implemented by hand (unless you can find a library somewhere for ObjC, Swift or C).
A few test cases:
Existing implementation - typescript (we used a library for z-base32)
constparts=email.split('@');if(parts.length!==2){returnnull;}const[user,recipientDomain]=parts;if(!user||!recipientDomain){returnnull;}constdirectDomain=recipientDomain.toLowerCase();constadvancedDomainPrefix=(directDomain==='localhost') ? '' : 'openpgpkey.';consthu=opgp.util.encodeZBase32(awaitopgp.crypto.hash.digest(opgp.enums.hash.sha1,Buf.fromUtfStr(user.toLowerCase())));constdirectHost=(typeofthis.port==='undefined') ? directDomain : `${directDomain}:${this.port}`;constadvancedHost=`${advancedDomainPrefix}${directHost}`;constuserPart=`hu/${hu}?l=${encodeURIComponent(user)}`;constadvancedUrl=`https://${advancedHost}/.well-known/openpgpkey/${directDomain}`;constdirectUrl=`https://${directHost}/.well-known/openpgpkey`;// ...Existing implementation - python, where we had to implement zbase32 ourselves:
classWkd(PubkeySource):
# https://datatracker.ietf.org/doc/draft-koch-openpgp-webkey-service/?include_text=1# https://www.sektioneins.de/en/blog/18-11-23-gnupg-wkd.html# https://metacode.biz/openpgp/web-key-directory__TIMEOUT= (3, 3)
deffind_pubkey(self, email:str=None):
user, domain=self._email_as_user_and_private_domain(email)
ifuserisNoneordomainisNone:
returnNonehu=self.__sha1_zbase32(user)
url_advanced=f'https://openpgpkey.{domain}/.well-known/openpgpkey/{domain}/hu/{hu}?l={user}'url_direct=f'https://{domain}/.well-known/openpgpkey/hu/{hu}?l={user}'# ...def__sha1_zbase32(self, user: str):
defchunk_string(string, length):
return (string[0+i:length+i] foriinrange(0, len(string), length))
defchars_from_int(int32):
result= []
shift=27for_inrange(4):
result.append("ybndrfg8ejkmcpqxot1uwisza345h769"[(int32>>shift) &31])
shift=shift-5returnresulthashed_bytes=hashlib.sha1(user.encode()).digest()
bits_string=bin(int.from_bytes(hashed_bytes, byteorder="big"))[2:]
chunks_of_20_bits=chunk_string(bits_string, 20)
offset_chunks_of_20_bits= [chunk+'000000000000'forchunkinchunks_of_20_bits]
ints= [int(bits, 2) forbitsinoffset_chunks_of_20_bits]
groups_of_4_chars= [chars_from_int(int32) forint32inints]
return"".join(sum(groups_of_4_chars, []))This is a pre-requisite for #296
part of #275
We'll need a way to construct WKD URLs with an email address as an input. Signature:
This will follow the following spec: https://tools.ietf.org/html/draft-koch-openpgp-webkey-service-11 - this uses z-base-32 which is different from base-32, and may need to be implemented by hand (unless you can find a library somewhere for ObjC, Swift or C).
A few test cases:
recipient.hello@example.comDIRECT-> https://example.com/.well-known/openpgpkey/hu/1sbjrcaf8m3zckmmuej93nx61yn1sttg?l=recipient.hellorecipient.hello@example.comADVANCED-> https://openpgpkey.example.com/.well-known/openpgpkey/example.com/hu/1sbjrcaf8m3zckmmuej93nx61yn1sttg?l=recipient.helloUPPER@EXAMPLE.COMDIRECT->https://example.com/.well-known/openpgpkey/hu/awhcnhf7a4ax8qha5u1rwymkfaswmjz8?l=UPPERUPPER@EXAMPLE.COMADVANCED-> https://openpgpkey.example.com/.well-known/openpgpkey/example.com/hu/awhcnhf7a4ax8qha5u1rwymkfaswmjz8?l=UPPERExisting implementation - typescript (we used a library for z-base32)
Existing implementation - python, where we had to implement zbase32 ourselves:
This is a pre-requisite for #296