{"id":11326,"date":"2015-05-22T20:05:46","date_gmt":"2015-05-22T20:05:46","guid":{"rendered":"https:\/\/www.bartbusschots.ie\/s\/?p=11326"},"modified":"2015-05-28T19:48:36","modified_gmt":"2015-05-28T19:48:36","slug":"xkpasswd-pm-becomes-crypthsxkpasswd","status":"publish","type":"post","link":"https:\/\/www.bartbusschots.ie\/s\/2015\/05\/22\/xkpasswd-pm-becomes-crypthsxkpasswd\/","title":{"rendered":"XKPasswd.pm becomes Crypt::HSXKPasswd"},"content":{"rendered":"<p>It&#8217;s been a while since I released a new version of <code>XKPasswd.pm<\/code>, the open source Perl module that powers the secure memorable password generator at <a href=\"http:\/\/www.xkpasswd.net\/\" target=\"_blank\">www.xkpasswd.net<\/a>. The main reason for the big gap is that I needed to learn some new skills to get the code to where I wanted it to be. There were three main problems I wanted solved:<\/p>\n<ol>\n<li>To get wide adoption, the Module needs to be available via <a href=\"http:\/\/www.cpan.org\/\" target=\"_blank\">CPAN<\/a><\/li>\n<li>The module needs unicode support to deal with non-English languages<\/li>\n<li>It needs to be easy to edit and tweak a config with the <a href=\"http:\/\/www.xkpasswd.net\/\" target=\"_blank\">www.xkpasswd.net<\/a> web interface, and then use it in your scripts.<\/li>\n<\/ol>\n<p>While solving those problems, I also took the opportunity to tidy up some other odds and ends in the code base. It&#8217;s not that code was broken, it just that a few parts of it had a bit of a fishy smell &#8211; it seemed like there was probably a better way to do that, and there was!<\/p>\n<p>So, here&#8217;s a summary of what&#8217;s changed from the the point of view of a user of the Module:<\/p>\n<ul>\n<li>The Packaging &#8211; the module has a new name, and is now packaged with <code>Module::Build<\/code>, so it&#8217;s easier to install, and ready for distribution via CPAN.<\/li>\n<li>Unicode Support &#8211; if it&#8217;s a unicode character, you can use it while generating passwords.<\/li>\n<li>Redesigned Word Sources &#8211; more bundled with the module, and easier to create your own.<\/li>\n<li>Redesigned Sources of Randomness &#8211; more bundled with the module, a better default, and easier to create you own.<\/li>\n<li>A switch to Named Arguments (in both the constructor and functional interface).<\/li>\n<\/ul>\n<p>I&#8217;ve put a lot of time and effort into developing this entirely free and open source module. If you find it useful, please consider making a donation:<\/p>\n<p style=\"text-align:center\"><!-- Begin PayPal Donations by https:\/\/www.tipsandtricks-hq.com\/paypal-donations-widgets-plugin -->\n\n<form action=\"https:\/\/www.paypal.com\/cgi-bin\/webscr\" method=\"post\">\n    <div class=\"paypal-donations\">\n        <input type=\"hidden\" name=\"cmd\" value=\"_donations\" \/>\n        <input type=\"hidden\" name=\"bn\" value=\"TipsandTricks_SP\" \/>\n        <input type=\"hidden\" name=\"business\" value=\"bart@bartificer.net\" \/>\n        <input type=\"hidden\" name=\"item_name\" value=\"XKPasswd\" \/>\n        <input type=\"hidden\" name=\"item_number\" value=\"XKPasswd\" \/>\n        <input type=\"hidden\" name=\"rm\" value=\"0\" \/>\n        <input type=\"hidden\" name=\"currency_code\" value=\"EUR\" \/>\n        <input type=\"image\" style=\"cursor: pointer;\" src=\"https:\/\/www.paypalobjects.com\/en_US\/i\/btn\/btn_donate_LG.gif\" name=\"submit\" alt=\"PayPal - The safer, easier way to pay online.\" \/>\n        <img loading=\"lazy\" decoding=\"async\" alt=\"\" src=\"https:\/\/www.paypalobjects.com\/en_US\/i\/scr\/pixel.gif\" width=\"1\" height=\"1\" \/>\n    <\/div>\n<\/form>\n<!-- End PayPal Donations -->\n<\/p>\n<p style=\"text-align:center;font-weight:bold;font-size:16pt\">*<a href=\"https:\/\/github.com\/bbusschots\/xkpasswd.pm\/releases\" title=\"XKPasswd.pm GitHub Releases\" target=\"_blank\">Download Beta of <code>Crypt::HSXKPasswd<\/code> via GitHub<\/a>*<\/p>\n<p><!--more--><\/p>\n<h2>Why The New Name?<\/h2>\n<p>The primary motivation for the change was CPAN. You need to respect the CPAN name-space, and that means not taking a root-level name just for the heck of it. Instead, I spent some time reviewing other password generation modules in CPAN to figure out where in the name-space the module would be most at home. In the end I decided on <code>Crypt<\/code>.<\/p>\n<p>As well as respecting the CPAN name-space, you also need to clearly position your module relative to other similar modules. What makes it different?<\/p>\n<p>There are already password generators inspired by XKCD on CPAN, <code>Crypt::XkcdPassword<\/code> for example. What makes this module different?<\/p>\n<p>Simply put, this module has two equally ideas at it&#8217;s core, Steve Gibson&#8217;s <a href=\"https:\/\/www.grc.com\/haystack.htm\" target=\"_blank\">Password Hay Stacks<\/a>, and the <a href=\"https:\/\/xkcd.com\/936\/\" target=\"_blank\">famous XKCD web comic about password strength<\/a>. The old name only referenced half of this important duo of inspirations.<\/p>\n<p><code>Crypt::HSXKPasswd<\/code> can create passwords exactly like the famous <code>correct horse battery staple<\/code> example from the comic, but that&#8217;s actually an edge-case. The module is designed to use words as a lattice around which a more secure, but still memorable, password can be built. The idea to use words comes from XKCD, the concept of separators and padding comes from Password Hay Stacks.<\/p>\n<h2>New Packaging<\/h2>\n<p>Earlier versions of this module were simply distributed as a single <code>.pm<\/code> file. There was no concept of an installer of any kind &#8211; users had to download the code from GitHub, save it to a folder of their choice, and then point their scripts at that folder with the help of a <code>use lib<\/code> directive. This was always sub-optimal, and proper packaging was always on my <em>to do<\/em> list. Well, now it&#8217;s done!<\/p>\n<p>The module is now packaged with <code>Module::Build<\/code>, the more modern of the two common Perl packagers. This allows me to generate <code>.tar.gz<\/code> bundles for distributing the module, which contain the code, as well as the build scripts needed to install it.<\/p>\n<p>One of the big reasons for choosing <code>Module::Build<\/code> is that it&#8217;s compatible with CPAN. Once the module has endured some beta testing, I&#8217;ll be uploading it to CPAN, so in future, you&#8217;ll be able to install it directly from there.<\/p>\n<h3><a name=\"install\"><\/a>Installing the Beta<\/h3>\n<p>In the mean time, the installation process is quite simple:<\/p>\n<p>Start the installation process by downloading the <code>.tar.gz<\/code> file for the most recent release <a href=\"https:\/\/github.com\/bbusschots\/xkpasswd.pm\/releases\" target=\"_blank\">from GitHub<\/a> (<a href=\"https:\/\/github.com\/bbusschots\/xkpasswd.pm\/releases\/tag\/v3.1.1\" target=\"_blank\">Crypt-HSXKPasswd-v3.1.1 BETA 1<\/a> at the moment). Once the file is downloaded, extract it, open a Terminal, and change directory into the newly extracted folder. It doesn&#8217;t matter where you extract this folder because you can delete it once the module is installed.<\/p>\n<p>In that folder, issue the following commands:<\/p>\n<pre>\r\nperl Build.PL\r\nsudo .\/Build installdeps\r\n.\/Build\r\n.\/Build test\r\nsudo .\/Build install\r\n<\/pre>\n<p><a href=\"https:\/\/www.bartbusschots.ie\/s\/2015\/05\/28\/installing-the-crypthsxkpasswd-betas\/\" target=\"_blank\">More detailed instructions here<\/a>.<\/p>\n<h2>Unicode Support<\/h2>\n<p>Previous versions of this module have suffered from the narrow word view that comes from living in an English speaking country. If a word contained a character other than a bare letter between <code>a<\/code> and <code>z<\/code>, the module simply skipped the word. No more &#8211; the module has broadened its world view with full Unicode support!<\/p>\n<p>By default the module uses UTF-8 for all inputs, but it can use any input encoding supported by Perl.<\/p>\n<p>Unfortunately, there is a price to pay for this new-found international awareness &#8211; backwards compatibility. Perl didn&#8217;t develop robust unicode support until version 5.16, so this new version of the module is incompatible with all versions of Perl older than Per 5.16. Given that Perl 5.16 was released in May 2012, don&#8217;t expect this to cause too many problems.<\/p>\n<p>Support for accented characters in passwords is by no means universal, so the module&#8217;s default behaviour is still to avoid generating passwords containing accents. But, that default has become significantly smarter. Rather than rejecting words with accented characters, the module will now happily ingest them and use them in passwords, but, when the password is returned, the accents will be stripped off. That is to say, the module&#8217;s default behaviour is to load the word <code>clich\u00c3\u00a9<\/code> without error, but to render it as <code>cliche<\/code> in passwords.<\/p>\n<p>If the site you are generating passwords for will happily accept accented characters, then you can override the default behaviour and have the module preserve the accents in the generated passwords. You do this by setting the new config variable <code>allow_accents<\/code> to <code>1<\/code>. All the presets have <code>allow_accents<\/code> set to <code>0<\/code>, but that can be easily override using the new named arguments (described in detail below). For example, to use the XKCD preset with accents enabled, you could do the following:<\/p>\n<pre class=\"brush: perl; title: ; notranslate\" title=\"\">\r\nmy $password = hsxkpasswd(\r\n    preset =&gt; &#039;XKCD&#039;,\r\n    preset_override =&gt; {allow_accents =&gt; 1}\r\n);\r\n<\/pre>\n<h2>Word Sources<\/h2>\n<p>Previous versions of the module have been built around a single source of words &#8211; dictionary files, i.e. text files with one word per line.<\/p>\n<p>Dictionary files are still supported, but, so are other sources of words. The module can now consume words from an instance of any class the extends <code>Crypt::HSXKPasswd::Dictionary<\/code>, and implements the method <code>word_list()<\/code>.<\/p>\n<p>The module now includes nine word sources ready for you to use:<\/p>\n<dl>\n  <dh><code>Crypt::HSXKPasswd::Dictionary::EN_Default<\/code><\/dh><\/p>\n<dd>As it&#8217;s name suggests, this is the module&#8217;s default word source. It contains the same English words that were in the sample dictionary file that shipped with previous versions of the module, but bundled into a module, making it easier to use.<\/dd>\n<p>  <dh><code>Crypt::HSXKPasswd::Dictionary::Basic<\/code><\/dh><\/p>\n<dd>This word source allows for the aggregation of one or more dictionary files and\/or arrays of words into a single dictionary. This is particularly convenient for people who speak multiple languages, and want to generate passwords contains words randomly chosen from any of the languages they speak.<\/dd>\n<p>  <dh><code>Crypt::HSXKPasswd::Dictionary::System<\/code><\/dh><\/p>\n<dd>This dictionary uses the Unix words file as its source of words. It&#8217;s obviously only available on Linux and Unix systems that have a words file, including Mac OS X.<\/dd>\n<p>  <dh><code>Crypt::HSXKPasswd::Dictionary::DE<\/code>, <code>Crypt::HSXKPasswd::Dictionary::ES<\/code>, <code>Crypt::HSXKPasswd::Dictionary::FR<\/code>, <code>Crypt::HSXKPasswd::Dictionary::IT<\/code>, <code>Crypt::HSXKPasswd::Dictionary::NL<\/code> &#038; <code>Crypt::HSXKPasswd::Dictionary::PT<\/code><\/dh><\/p>\n<dd>German, Spanish, French, Italian, Dutch\/Flemish &#038; Portuguese dictionaries, all based on the free and open source dictionary files from the <a href=\"http:\/\/www.winedt.org\" target=\"_blank\">WinEdt<\/a> project. These dictionaries are new, and need to have the rough edges knocked off them &#8211; see the <em>Help Needed!<\/em> section below for details.<\/dd>\n<\/dl>\n<p>For example, to use the French dictionary and permit accented characters in the generated passwords, you could do something like:<\/p>\n<pre class=\"brush: perl; title: ; notranslate\" title=\"\">\r\nmy $password = hsxkpasswd(\r\n    dictionary =&gt; Crypt::HSXKPasswd::Dictionary::FR-&gt;new(),\r\n    preset =&gt; &#039;WEB32&#039;,\r\n    preset_override =&gt; {allow_accents =&gt; 1}\r\n);\r\n<\/pre>\n<h3>Help Needed!<\/h3>\n<p>The German, Spanish, French, Italian, Dutch\/Flemish &#038; Portuguese dictionaries are all based on the <a href=\"http:\/\/www.winedt.org\/Dict\/\" target=\"_blank\">free and open-source dictionary files for WinEdit<\/a>. These dictionaries are designed to be used in a word processor, not for use a list of common words. This means that are all too big, and they all contain words that would definitely not be considered memorable by most.<\/p>\n<p>I&#8217;m looking for native speakers of each of these languages to help me prune these dictionaries down to just a few thousand truly common words, like I did a few years ago when creating the English dictionary the module uses by default.<\/p>\n<p>You&#8217;ll find copies of the dictionary files, with their open source licenses and credits, in the <code>share<\/code> inside the installer bundle. Anyone who helps me with the files will get credited in them, and the license will remain as it is (BSD in some cases, GPL in others).<\/p>\n<h2>Sources of Random Numbers<\/h2>\n<p>All versions of this module have made it possible to supply your own random number generator (RNG), but previous versions didn&#8217;t make that as easy as it could have been, and shipped with only one standard RNG.<\/p>\n<p>You can now create your own RNGs by extending the class <code>Crypt::HSXKPasswd::RNG<\/code>, and implementing the method <code>random_numbers()<\/code>.<\/p>\n<p>The module ships with five RNGs ready for your use:<\/p>\n<dl>\n<dt><code>Crypt::HSXKPasswd::RNG::Basic<\/code><\/dt>\n<dd>This RNG uses Perl&#8217;s built-in <code>rand()<\/code> function to generate random numbers. Using <code>rand()<\/code> makes this RNG fast, and means it doesn&#8217;t rely on any non-standard modules. Unfortunately, there is also a significant draw-back &#8211; <code>rand()<\/code> is not actually a very good RNG! I would argue that it&#8217;s <em>good enough<\/em> for most users, but none the less, my recommendation would be to avoid it unless none of the alternatives will work for you.<\/dd>\n<dt><code>Crypt::HSXKPasswd::RNG::DevUrandom<\/code><\/dt>\n<dd>Linux and Unix systems (Mac OS X included), come with their own OS-provided source of randomness, the special file <code>\/dev\/urandom<\/code>. This RNG uses <code>\/dev\/urandom<\/code> to generate random numbers. It&#8217;s fast, provides good quality randomness, but is sadly only available on Unix, Linux, and OS X systems.<\/dd>\n<dt><code>Crypt::HSXKPasswd::RNG::Math_Random_Secure<\/code><\/dt>\n<dd>As its name implies, this RNG uses the non-standard module <code>Math::Random::Secure<\/code> to generate random numbers. If you can install <code>Math::Random::Secure<\/code> on your system, this is the RNG I would recommend, it generates very high quality randomness, and is quite fast.<\/dd>\n<dt><code>Crypt::HSXKPasswd::RNG::Data_Entropy<\/code><\/dt>\n<dd>As its name implies, this RNG uses the non-standard module <code>Data::Entropy::Algorithms<\/code> to generate random numbers. It generates high quality random numbers, but it&#8217;s slow. I found it to be about six times slower than perl&#8217;s build-in <code>rand()<\/code> function in my testing.<\/dd>\n<dt><code>Crypt::HSXKPasswd::RNG::RandomDotOrg<\/code><\/dt>\n<dd>This RNG uses <a href=\"https:\/\/www.random.org\/clients\/http\/\" target=\"_blank\">Random.Org&#8217;s HTTP API<\/a> to source random numbers. As it relies on a web service, it&#8217;s inevitably much slower than the other RNGs, but the random numbers are of a very high quality, so it might be a good option for the somewhat paranoid \ud83d\ude42 To use this RNG you need to install the following packages which <code>Crypt::HSXKPasswd<\/code> declares as recommended rather than required: <code>Email::Valid<\/code>, <code>URI<\/code>, <code>LWP::UserAgent<\/code> &#038; <code>Mozilla::CA<\/code>.<\/dd>\n<\/dl>\n<p>The module&#8217;s default behaviour is to use the best RNG available on your system.  It will first try <code>Crypt::HSXKPasswd::RNG::Math_Random_Secure<\/code>, then <code>Crypt::HSXKPasswd::RNG::Data_Entropy<\/code>, then <code>Crypt::HSXKPasswd::RNG::DevUrandom<\/code>, and only then fall back to <code>Crypt::HSXKPasswd::RNG::Basic<\/code>. You&#8217;ll know if the module falls back to <code>Crypt::HSXKPasswd::RNG::Basic<\/code>, because it will issues a warning if it does.<\/p>\n<h2>Named Arguments<\/h2>\n<p>When creating a single password using the functional interface (<code>hsxkpasswd()<\/code>), or when creating a <code>Crypt::HSXKPasswd<\/code> object, you need to be able to easily specify all the customisations you require. Specifically, you want to specify between zero and three of the the following, a word source, a config, and a an RNG. Given that there are multiple ways to specify a word source, and multiple ways to specify a config, there are a lot of possible permutations to cater for. Named arguments are the only way cater for all the possible combinations in a sane.<\/p>\n<p>If you&#8217;re not familiar with named arguments, they work by specifying one or more name-value pairs where the name-value pairs are separated by <code>,<\/code>s and the names and the values by <code>=><\/code>s. For clarity, named arguments are often written one per line, but that&#8217;s purely a stylistic choice. Below is an example showing how to generate a password from a custom dictionary file, the <code>APPLEID<\/code> preset, and the default RNG:<\/p>\n<pre class=\"brush: perl; title: ; notranslate\" title=\"\">\r\nmy $password = hsxkpasswd(\r\n  dictionary_file =&gt; &#039;my_dict.txt&#039;,\r\n  preset =&gt; &#039;APPLEID&#039;\r\n);\r\n<\/pre>\n<p>Note that since there is now a default word source, default, config, and default RNG, you can use both the constructor and the functional interface with no argument at all:<\/p>\n<pre class=\"brush: perl; title: ; notranslate\" title=\"\">\r\n# a single password using the functional interface with all defaults\r\nmy $password = hsxkpasswd();\r\n\r\n# an object with all defaults\r\nmy $hsxkpasswd_obj = Crypt::HSXKPasswd-&gt;new();\r\n<\/pre>\n<p>Let&#8217;s look at the three groups of named arguments in detail.<\/p>\n<h3>Specifying a Word Source<\/h3>\n<p>Words can be loaded from a text file, a reference to an array of words, or an instance of a class that extends <code>Crypt::HSXKPasswd::Dictionary<\/code>. There is a different named argument available for each of these options:<\/p>\n<dl>\n  <dh><code>dictionary<\/code><\/dh><\/p>\n<dd>An instance of a class that extends <code>Crypt::HSXKPasswd::Dictionary<\/code>.<\/dd>\n<p>  <dh><code>dictionary_list<\/code><\/dh><\/p>\n<dd>A reference to an array of words.<\/dd>\n<p>  <dh><code>dictionary_file<\/code><\/dh><\/p>\n<dd>The path to a dictionary file. When using this argument, you can optionally include a second named argument, <code>dictionary_file_encoding<\/code>, to specify the file&#8217;s character encoding. The module defaults to treating input files as UTF-8.<\/dd>\n<\/dl>\n<p>You should only ever use one of <code>dictionary<\/code>, <code>dictionary_list<\/code> and <code>dictionary_file<\/code> in a single function call. If multiple are specified, only the one with the highest priority will be used, and the rest will be ignored. The list above shows the options in descending priority.<\/p>\n<p>If you don&#8217;t specify a word source, the module will use an instance of <code>Crypt::HSXKPasswd::Dictionary::EN_Default<\/code>.<\/p>\n<h3>Specifying A Config<\/h3>\n<p>The module can accept a configs as a preset name (with optional key overrides), as a config hasherf, or as a JSON string representing a valid config hashref.<\/p>\n<p>The following named arguments are available for specifying a config:<\/p>\n<dl>\n<dt><code>config<\/code><\/dt>\n<dd>A valid config hashref.<\/dd>\n<dt><code>config_json<\/code><\/dt>\n<dd>A JSON string representing a valid config hashref. This feature is only available if you have the standard Perl JSON library installed (available via CPAN).<\/dd>\n<dt><code>preset<\/code><\/dt>\n<dd>Use one of the presets defined by the module. You can optionally override one or more keys in the preset by passing a hashref using the named argument <code>preset_overrides<\/code>.<\/dd>\n<\/dl>\n<p>You should only ever use one of <code>config<\/code>, <code>config_json<\/code> and <code>preset<\/code> in a single function call. If multiple are specified, only the one with the highest priority will be used, and the rest will be ignored. The list above shows the options in descending priority.<\/p>\n<p>When you save a config using the Load\/Save tab at <a href=\"http:\/\/www.xkpasswd.net\/\" target=\"_blank\">www.xkpasswd.net<\/a>, the config is output in JSON format. The <code>config_json<\/code> named argument makes it easy to build a config you like using the web GUI, and then use that config in your scripts.<\/p>\n<p>By default the module uses the preset <code>DEFAULT<\/code>.<\/p>\n<h3>Specifying an RNG<\/h3>\n<p>There is only one named argument for controlling random number generation, <code>rng<\/code>, and the associated value must be an instance of a class that extends <code>Crypt::HSXKPasswd::RNG<\/code>.<\/p>\n<p>As described earlier in the article, by default the module will use the most secure RNG available on your system. Unless you write your own custom RNG, or want to use <code>Crypt::HSXKPasswd::RNG::RandomDotOrg<\/code>, my advice would be to allow the module choose the most secure available RNG for you by not specifying an <code>rng<\/code> argument.<\/p>\n<h3>Finally &#8211; Reporting Bugs &#038; Contributing<\/h3>\n<p>There are literally thousands of new or edited lines of code in this module. I&#8217;ve obviously done my own testing, but it&#8217;s almost inevitable that I&#8217;ve missed something somewhere. If you stumble into any bugs, please let me know by <a href=\"https:\/\/github.com\/bbusschots\/xkpasswd.pm\/issues\" target=\"_blank\">opening an issue on the project&#8217;s GitHub page<\/a>.<\/p>\n<p>You can also use the GitHub issue tracker to suggest improvements or additions.<\/p>\n<p>Finally for any interested developers out there &#8211;  pull requests are welcome, provided the code works, the code style is consistent with the rest of the module, and the code passes <code>PerlCritic<\/code> run using the settings in the <code>.perlcriticrc<\/code> file included in the module&#8217;s GitHub project.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>It&#8217;s been a while since I released a new version of XKPasswd.pm, the open source Perl module that powers the secure memorable password generator at www.xkpasswd.net. The main reason for the big gap is that I needed to learn some new skills to get the code to where I wanted it to be. There were [&hellip;]<\/p>\n","protected":false},"author":3,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[12,440,17,16],"tags":[410,267,457],"series":[],"class_list":["post-11326","post","type-post","status-publish","format-standard","hentry","category-computers-tech","category-tech-projects","category-security","category-programming","tag-hsxkpasswd","tag-perl","tag-software-release"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/p7t9xK-2WG","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/www.bartbusschots.ie\/s\/wp-json\/wp\/v2\/posts\/11326","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.bartbusschots.ie\/s\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.bartbusschots.ie\/s\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.bartbusschots.ie\/s\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/www.bartbusschots.ie\/s\/wp-json\/wp\/v2\/comments?post=11326"}],"version-history":[{"count":8,"href":"https:\/\/www.bartbusschots.ie\/s\/wp-json\/wp\/v2\/posts\/11326\/revisions"}],"predecessor-version":[{"id":11401,"href":"https:\/\/www.bartbusschots.ie\/s\/wp-json\/wp\/v2\/posts\/11326\/revisions\/11401"}],"wp:attachment":[{"href":"https:\/\/www.bartbusschots.ie\/s\/wp-json\/wp\/v2\/media?parent=11326"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.bartbusschots.ie\/s\/wp-json\/wp\/v2\/categories?post=11326"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.bartbusschots.ie\/s\/wp-json\/wp\/v2\/tags?post=11326"},{"taxonomy":"series","embeddable":true,"href":"https:\/\/www.bartbusschots.ie\/s\/wp-json\/wp\/v2\/series?post=11326"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}