This commit is contained in:
Amolith 2019-06-28 01:09:37 -04:00
parent a5ad6cbd63
commit a2029e7c8c
Signed by: Amolith
GPG Key ID: 51FD40936DB0065B
30 changed files with 43847 additions and 268 deletions

View File

@ -1,3 +1,5 @@
source "https://rubygems.org"
gem 'jekyll-compose', group: [:jekyll_plugins]
gem 'jekyll-target-blank'

View File

@ -31,6 +31,9 @@ GEM
jekyll (~> 3.0)
jekyll-sass-converter (1.5.2)
sass (~> 3.4)
jekyll-target-blank (1.1.1)
jekyll (~> 3.0)
nokogiri (~> 1.8.2)
jekyll-watch (2.1.2)
listen (~> 3.0)
kramdown (1.17.0)
@ -40,6 +43,9 @@ GEM
rb-inotify (~> 0.9, >= 0.9.7)
ruby_dep (~> 1.2)
mercenary (0.3.6)
mini_portile2 (2.3.0)
nokogiri (1.8.5)
mini_portile2 (~> 2.3.0)
pathutil (0.16.2)
forwardable-extended (~> 2.6)
public_suffix (3.0.3)
@ -59,6 +65,7 @@ PLATFORMS
DEPENDENCIES
jekyll-compose
jekyll-target-blank
BUNDLED WITH
2.0.1

View File

@ -30,3 +30,6 @@ livereload: true
jekyll_compose:
auto_open: true
plugins:
- jekyll-target-blank

View File

@ -5,12 +5,12 @@
<link rel="stylesheet" href="{{ site.baseurl }}/assets/vendor/highlight/styles/solarized_dark.css">{% endif %}
<link rel="stylesheet" href="{{ "/assets/vendor/font-awesome/css/fork-awesome.min.css" | prepend: site.baseurl }}">
<link rel="apple-touch-icon" sizes="180x180" href="favicons/apple-touch-icon.png?v=wAXex2OGrl">
<link rel="icon" type="image/png" sizes="32x32" href="favicons/favicon-32x32.png?v=wAXex2OGrl">
<link rel="icon" type="image/png" sizes="16x16" href="favicons/favicon-16x16.png?v=wAXex2OGrl">
<link rel="manifest" href="favicons/site.webmanifest?v=wAXex2OGrl">
<link rel="mask-icon" href="favicons/safari-pinned-tab.svg?v=wAXex2OGrl" color="#5bbad5">
<link rel="shortcut icon" href="favicons/favicon.ico?v=wAXex2OGrl">
<link rel="apple-touch-icon" sizes="180x180" href="/favicons/apple-touch-icon.png?v=wAXex2OGrl">
<link rel="icon" type="image/png" sizes="32x32" href="/favicons/favicon-32x32.png?v=wAXex2OGrl">
<link rel="icon" type="image/png" sizes="16x16" href="/favicons/favicon-16x16.png?v=wAXex2OGrl">
<link rel="manifest" href="/favicons/site.webmanifest?v=wAXex2OGrl">
<link rel="mask-icon" href="/favicons/safari-pinned-tab.svg?v=wAXex2OGrl" color="#5bbad5">
<link rel="shortcut icon" href="/favicons/favicon.ico?v=wAXex2OGrl">
<meta name="msapplication-TileColor" content="#494848">
<meta name="msapplication-config" content="favicons/browserconfig.xml?v=wAXex2OGrl">
<meta name="theme-color" content="#ffffff">

View File

@ -5,30 +5,24 @@
<li class="menu-entry"><a href="{{ '/about' | prepend: site.baseurl }}">About</a></li>
<li class="menu-entry"><a href="{{ '/contact' | prepend: site.baseurl }}">Contact</a></li>
<li class="menu-entry"><a href="{{ '/blog' | prepend: site.baseurl }}">Blog</a></li>
<li class="menu-entry"><a href="{{ '/friends' | prepend: site.baseurl }}">Friends</a></li>
<li class="menu-entry"><a href="{{ '/privacy' | prepend: site.baseurl }}">Privacy</a></li>
</ul>
</div>
<ul class="social-links">
<a href="/feed.xml" title="The RSS feed for my blog" class="social-linkes-entry" target="_blank">
<div class="social-links">
<a href="/feed.xml" title="The RSS feed for my blog" aria-label="Subscribe to the RSS feed for my blog" class="social-linkes-entry" target="_blank">
<i class="fa fa-rss-square"></i>
</a>
<a href="/me/" title="About Amolith" class="social-links-entry">
<a href="/me/" title="About Amolith" aria-label="Read more about me" class="social-links-entry">
<i class="fa fa-info-circle"></i>
</a>
{% if site.author.mastodon %}
<a rel="me" title="Mastodon, a decentralised social network" href="https://masto.nixnet.xyz/@{{ site.author.mastodon }}" class="social-links-entry" target="_blank">
<a rel="me" rel="noreferrer" title="Mastodon, a decentralised social network" aria-label="Visit my Mastodon profile" href="https://masto.nixnet.xyz/@{{ site.author.mastodon }}" class="social-links-entry" target="_blank">
<i class="fa fa-mastodon"></i>
</a>
{% endif %}
{% if site.author.telegram %}
<a href="https://t.me/{{ site.author.telegram }}" title="Message me on Telegram"class="social-links-entry" target="_blank">
<a href="https://t.me/{{ site.author.telegram }}" rel="noreferrer" title="Message me on Telegram" aria-label="Message me on Telegram" class="social-links-entry" target="_blank">
<i class="fa fa-telegram"></i>
</a>
{% endif %}
{% if site.author.email %}
<a href="mailto:{{ site.author.email }}" title="Send me a GPG-encrypted email" class="social-links-entry" target="_blank">
<a href="mailto:{{ site.author.email }}" title="Send me a GPG-encrypted email" aria-label="Send me a GPG-encrypted email" class="social-links-entry" target="_blank">
<i class="fa fa-envelope"></i>
</a>
{% endif %}
</ul>
</div>
</header>

View File

@ -7,7 +7,7 @@
{% endfor %}
<li class="categories-item"><a href="{{ '/' | prepend: site.baseurl }}">All</a></li>
</ul>
<div class="explore-label">Website source available <a href="https://git.nixnet.xyz/Amolith/NixNet">here</a></div>
<div class="explore-label">All content is licensed under <a href="https://creativecommons.org/licenses/by/4.0/" target="_blank">CC-BY 4.0</a></div>
<div class="explore-label">Website source available on <a href="https://git.nixnet.xyz/Amolith/NixNet" rel="noreferrer">Gitea</a></div>
<div class="explore-label">All content is licensed under <a href="https://creativecommons.org/licenses/by/4.0/" rel="noreferrer" target="_blank">CC-BY 4.0</a></div>
<div class="explore-label"><i>(unless otherwise stated)</i></div>
</div>

View File

@ -1,8 +1,8 @@
<div class="explore">
<div class="explore-divider">*****</div>
<div class="explore-label">Website source available on <a href="https://git.nixnet.xyz/NixNet/nixnet">Gitea</a></div>
<div class="explore-label">Made with ❤️ and <a href="https://jekyllrb.com/" target="_blank">Jekyll</a> by <a href="https://nixnet.xyz/me/" target="_blank">Amolith</a></div>
<div class="explore-label">All content is licensed under <a href="https://creativecommons.org/licenses/by/4.0/" target="_blank">CC-BY 4.0</a></div>
<div class="explore-label">Website source available on <a href="https://git.nixnet.xyz/NixNet/nixnet" rel="noreferrer">Gitea</a></div>
<div class="explore-label">Made with ❤️ and <a href="https://jekyllrb.com/" rel="noreferrer" target="_blank">Jekyll</a> by <a href="https://nixnet.xyz/me/" target="_blank">Amolith</a></div>
<div class="explore-label">All content is licensed under <a href="https://creativecommons.org/licenses/by/4.0/" rel="noreferrer" target="_blank">CC-BY 4.0</a></div>
<div class="explore-label"><i>(unless otherwise stated)</i></div>
<div class="explore-label"><a href="http://l4qlywnpwqsluw65ts7md3khrivpirse744un3x7mlskqauz5pyuzgqd.onion/">l4qlywnpwqsluw65ts7md3khrivpirse744un3x7mlskqauz5pyuzgqd.onion</a></div>
</div>

View File

@ -1,5 +1,6 @@
---
layout: default
description: Amolith's blog on various tech-related topics
---
{% include page/title.html %}

View File

@ -1,5 +1,5 @@
<!DOCTYPE html>
<html class="" lang="en-US">
<html lang="en">
<head>
{% include meta_tags/base.html %}
{% include meta_tags/sharing.html %}

8
_layouts/home.html Normal file
View File

@ -0,0 +1,8 @@
---
layout: default
---
{% include page/title.html %}
{{ content }}
{% include page/footer.html %}

View File

@ -2,7 +2,8 @@
layout: default
---
{% include page/title.html %}
<div class="content">
{{ content }}
</div>
{% include page/footer.html %}

View File

@ -21,4 +21,4 @@ A great way to make this faster and simpler is to put an alias in your shell's `
echo "alias weather='curl sky.webionite.com/f/location'" >> ~/.bashrc
```
If you ever forget how to use the tool, just run `curl sky.webionite.com` and you'll be given instructions.
![](/assets/weather.png)
![screenshot of the output of the command. it shows two rows of four boxes with ascii art depicting rain, overcast clouds, and the sun obscured by clouds. it shows the temperature and the time of day. everything is coloured and looks very attractive.](/assets/weather.png)

View File

@ -6,8 +6,8 @@ description: Protecting yourself from malicious third parties leveraging DNS and
cover: /assets/posts/privacy.png
date: 2019-02-05 10:53 -0500
---
<center><h4>This post was mirrored from <a href="https://t.me/PrivacyToday">Privacy Today</a> on Telegram.</h4></center>
<center><h4><a href="https://t.me/PrivacyToday">t.me/PrivacyToday</a></h4></center>
<center><h4>This post was mirrored from <a rel="noreferrer" href="https://t.me/PrivacyToday">Privacy Today</a> on Telegram.</h4></center>
<center><h4><a rel="noreferrer" href="https://t.me/PrivacyToday">t.me/PrivacyToday</a></h4></center>
<br/>
Due to recent events we felt compelled to write an impromptu article on this matter. It's intended for all audiences so it will be kept simple - technical details may be posted later.
@ -72,7 +72,7 @@ This site will look absolutely fine to you; it has https in the URL and, if you
It now receives all the communication you intended to send to the original. This bypasses the checks created to avoid it. You won't receive error messages, your browser won't complain.
All your data is compromised!
All your data is compromised!
## 4. Conclusion
@ -85,7 +85,7 @@ All your data is compromised!
**Do not ever install a 3rd party root certificate!** There are very few exceptions why you would want to do so and none of them are applicable to general end users.
Do not fall for clever marketing that ensures "ad blocking", "military grade security", or something similar. There are methods of using DNS resolvers on their own to enhance your privacy but installing a 3rd party root certificate never makes sense. You are opening yourself up to extreme abuse.
Do not fall for clever marketing that ensures "ad blocking", "military grade security", or something similar. There are methods of using DNS resolvers on their own to enhance your privacy but installing a 3rd party root certificate never makes sense. You are opening yourself up to extreme abuse.
## 5. Seeing It Live
@ -111,8 +111,8 @@ Here is the link: [https-interception.info.tm](http://https-interception.info.tm
## 6. Further Information
If you are interested in more technical details, let us know. If there is enough interest, we might write a more in-depth article but, for now, the important part is sharing the basics so you can make an informed decision and not fall for marketing and straight up fraud. Feel free to suggest other topics that are important to you.
If you are interested in more technical details, let us know. If there is enough interest, we might write a more in-depth article but, for now, the important part is sharing the basics so you can make an informed decision and not fall for marketing and straight up fraud. Feel free to suggest other topics that are important to you.
<br/>
<br/>
<center><p>For more information/feedback/corrections, join <a href="https://t.me/PrivacyToday">Privacy Today</a> on Telegram.</p></center>
<center><p>This post is licensed under <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/">CC BY-NC-SA 4.0</a> and was mirrored with permission.</p></center>
<center><p>For more information/feedback/corrections, join <a rel="noreferrer" href="https://t.me/PrivacyToday">Privacy Today</a> on Telegram.</p></center>
<center><p>This post is licensed under <a rel="noreferrer" href="https://creativecommons.org/licenses/by-nc-sa/4.0/">CC BY-NC-SA 4.0</a> and was mirrored with permission.</p></center>

View File

@ -16,7 +16,7 @@ If that's all you intend to do, this should be sufficient and there's no need to
# For domains you *don't* own
There are a few things I used that worked in harmony to verify my other accounts. [Keybase](https://keybase.io/) was the most useful for this purpose. It is a proprietary service but I deem the level of proof it facilitates worth compromising for.
The other tool I used was [GPG](https://gnupg.org/). For the sake of keeping it simple, *this* guide will just deal with GPG from within Keybase. I ***really*** recommend actually learning to use GPG on its own; it's wonderful for protecting your privacy and verifying your identity in a multitude of situations. The next post will be on using GPG *outside* of Keybase for this so [stay tuned](nixnet.xyz/feed.xml).
The other tool I used was [GPG](https://gnupg.org/). For the sake of keeping it simple, *this* guide will just deal with GPG from within Keybase. I ***really*** recommend actually learning to use GPG on its own; it's wonderful for protecting your privacy and verifying your identity in a multitude of situations. The next post will be on using GPG *outside* of Keybase for this so [stay tuned](/feed.xml).
## Generating your key
After creating your Keybase account, click "add a PGP key", "I need a public key", then enter the requisite information. You should use whatever name is associated with the account you'll be emailing Archive.org from as well as that address. Wait a bit while it generates the key . . .

View File

@ -1,6 +1,7 @@
;
@font-face {
font-family: 'Open Sans';
font-display: auto;
font-style: normal;
font-weight: 300;
src: url('assets/fonts/open-sans-v15-latin-300.eot'); /* IE9 Compat Modes */
@ -13,6 +14,7 @@
}
@font-face {
font-family: 'Open Sans';
font-display: auto;
font-style: italic;
font-weight: 300;
src: url('/assets/fonts/open-sans-v15-latin-300italic.eot'); /* IE9 Compat Modes */
@ -25,6 +27,7 @@
}
@font-face {
font-family: 'Inconsolata';
font-display: auto;
font-style: normal;
font-weight: 400;
src: url('/assets/fonts/inconsolata-v16-latin-regular.eot'); /* IE9 Compat Modes */
@ -37,6 +40,7 @@
}
@font-face {
font-family: 'Inconsolata';
font-display: auto;
font-style: normal;
font-weight: 700;
src: url('/assets/fonts/inconsolata-v16-latin-700.eot'); /* IE9 Compat Modes */
@ -49,6 +53,7 @@
}
@font-face {
font-family: 'Overpass';
font-display: auto;
font-style: normal;
font-weight: 400;
src: url('/assets/fonts/overpass-v2-latin-regular.eot'); /* IE9 Compat Modes */

View File

@ -1,5 +1,5 @@
---
layout: page
layout: home
title: About
subtitle: 'A little bit about NixNet.xyz and some financial information'
description: A little bit about NixNet.xyz and some financial information
@ -14,28 +14,25 @@ permalink: /about/
<center>
<h1>Finance</h1>
</center>
<p>At the moment, all the sites I host are running on <a href="https://www.netcup.eu/vserver/vps.php" target="_blank">netcup GmbH's 500 G8</a> VPS. I pay <b>$6.10/mo</b> in lump sums of <b>$36.60</b> every six months. The domain <a href="https://nixnet.xyz" target="_blank">nixnet.xyz</a> is registered with <a href="http://gandi.net" target="_blank">gandi.net</a> and it renews at <b>$13.63/yr</b>. I use Gandi because they have WHOIS privacy by default, every domain comes with two inboxes and unlimited aliases for both. One is <a href="mailto:amolith@nixnet.xyz">amolith@nixnet.xyz</a> and the other uses my real name rather than my pseudonym. My plans are to upgrade to the 1000 G8 (on the same page) and add a <a href="https://www.netcup.eu/vserver/storagespace.php" target="_blank">Tariff A storage server</a>. This would cost $4.07/mo. I've also added the domain, nixnet.xyz to the goal, which is $13/year ($0.27/mo). My goal is $4.34/week <i>exactly</i> so I can upgrade VPSs, add a storage server, and not have anything left over.</p>
<p>At the moment, all the sites I host are running on <a href="https://www.netcup.eu/vserver/vps.php" rel="noreferrer" target="_blank">netcup GmbH's 500 G8</a> VPS. I pay <b>$6.10/mo</b> in lump sums of <b>$36.60</b> every six months. The domain <a href="/" rel="noreferrer" target="_blank">nixnet.xyz</a> is registered with <a href="http://gandi.net" rel="noreferrer" target="_blank">gandi.net</a> and it renews at <b>$13.63/yr</b>. I use Gandi because they have WHOIS privacy by default, every domain comes with two inboxes and unlimited aliases for both. One is <a href="mailto:amolith@nixnet.xyz">amolith@nixnet.xyz</a> and the other uses my real name rather than my pseudonym. My plans are to upgrade to the 1000 G8 (on the same page) and add a <a href="https://www.netcup.eu/vserver/storagespace.php" rel="noreferrer" target="_blank">Tariff A storage server</a>. This would cost $4.07/mo. I've also added the domain, nixnet.xyz to the goal, which is $13/year ($0.27/mo). My goal is $4.34/week <i>exactly</i> so I can upgrade VPSs, add a storage server, and not have anything left over.</p>
</h1>
</div>
</div>
<center>
<a href="https://liberapay.com/Amolith/donate" target="_blank"><button class="donate"><i class="fa fa-liberapay"></i> Liberapay</button></a>
<!--<a href="https://ko-fi.com/Amolith" target="_blank"><button class="donate"><i class="fa fa-coffee"></i> Ko-fi</button></a>-->
<a href="https://flattr.com/@Amolith" target="_blank"><button class="donate"><i class="fa fa-refresh"></i> Flattr</button></a>
<a href="https://tippeee.com/amolith" target="_blank"><button class="donate"><i class="fa fa-tipeee"></i> tipeee</button></a>
<a href="https://liberapay.com/Amolith/donate" rel="noreferrer" target="_blank"><button class="donate"><i class="fa fa-liberapay"></i> Liberapay</button></a>
</center>
<div class="content">
<center>
<p>If you want to donate in crypto currencies, I accept <a href="https://bitcoin.org/en/" target="_blank">Bitcoin</a> and <a href="https://litecoin.org/" target="_blank">Litecoin</a> though I do prefer Litecoin because of its speed. If you do crypto on mobile, you can scan the QR codes with your preferred app or tap them to open the appropriate app. The address is also below for other methods.</p>
<p>If you want to donate in crypto currencies, I accept <a href="https://bitcoin.org/en/" rel="noreferrer" target="_blank">Bitcoin</a> and <a href="https://litecoin.org/" rel="noreferrer" target="_blank">Litecoin</a> though I do prefer Litecoin because of its speed. If you do crypto on mobile, you can scan the QR codes with your preferred app or tap them to open the appropriate app. The address is also below for other methods.</p>
</div>
<div class="flex-wrapper">
<div class="flex-cards">
<div class="crypto-card">
<h1><a title="Bitcoin" href="bitcoin:1Q3o8Wtji2QS566BExdcPGMk76NjJgHrcz"><img src="/assets/btc.png"></img></a></h1>
<h1><a title="Bitcoin" href="bitcoin:1Q3o8Wtji2QS566BExdcPGMk76NjJgHrcz"><img src="/assets/btc.png" alt="Bitcoin QR code"></img></a></h1>
<h2>Bitcoin</h2>
<p>1Q3o8Wtji2QS566BExdcPGMk76NjJgHrcz</p>
</div>
<div class="crypto-card">
<h1><a title="Litecoin" href="litecoin:LUUbRvipXwcf3pFAXLVJV4jYmK3uBYBJcq"><img src="/assets/ltc.png"></img></a></h1>
<h1><a title="Litecoin" href="litecoin:LUUbRvipXwcf3pFAXLVJV4jYmK3uBYBJcq"><img src="/assets/ltc.png" alt="Litecoin QR code"></img></a></h1>
<h2>Litecoin</h2>
<p>LUUbRvipXwcf3pFAXLVJV4jYmK3uBYBJcq</p>
</div>

View File

@ -71,184 +71,245 @@ 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
=YfBo
VTxxovbOsVPAwbsx381A2i3U/W859gIYna3gHokDfgQTAQgBaAIbAwULCQgHAwUV
CgkICwQWAgEAWxSAAAAAABIAQHByb29mQG1ldGFjb2RlLmJpemh0dHBzOi8vZ2lz
dC5naXRodWIuY29tL0Ftb2xpdGgvZDMwMTZkN2E1MzI5NDRhZjhhN2RkYzA5ODk4
ZDUzMGMyFIAAAAAAEgAXcHJvb2ZAbWV0YWNvZGUuYml6ZG5zOm5peG5ldC54eXo/
dHlwZT1UWFQ8FIAAAAAAEgAhcHJvb2ZAbWV0YWNvZGUuYml6aHR0cHM6Ly9tYXN0
by5uaXhuZXQueHl6L0BhbW9saXRoZBSAAAAAABIASXByb29mQG1ldGFjb2RlLmJp
emh0dHBzOi8vd3d3LnJlZGRpdC5jb20vdXNlci9BbW9saXRoL2NvbW1lbnRzL2J4
enJvei9ncGdfa2V5X3ZlcmlmaWNhdGlvbi8WIQR13TLKG/7qauQNgjxR/UCTbbAG
WwUCXQXUOQUJBrcyfgAKCRBR/UCTbbAGWzezEAC07EO0+OfUkZj1ev1YbxEcC7kL
J9WnDa1sFe7x2EpH9Z8SyUkBDXW8YktrBPg4fWls3AVSyfe7U5/TtA5M6WcRt4UR
YbHAS8FFS20BPRWK6FoSexSy1dtkOBXMT3hn9X0RQoDDTB3w9/bAjq8r4zMvb1+n
H1UGJh3g5tYAjyCXfbSz30bfZlkbhc57tMiPWG3RyOiiyhUEfXkMnlNK5ugj1RLQ
qFxKWo8B6y0MJOxSNaFrGwJbbJtkN6f3AavzIFPwyhemKfT/rEDGvigWr7G7CfAr
1pqurTY+RTlUUhQYG1VLb05yc0D1AXRjFcZWiRw6D2BxNi5MuEwbWnYhNmSom6H/
FSThxn/hxAgQpapjXkC8jqy6/gTpqRigvdlICGzlpmKix61Cb0laV+7+P81kr8x9
wfjZWNwVIlTZ/BuOAYGJstxKvkAiEG3qUF8oh36vM5xGnzfK/Ewz/JJHoes0SkX6
XIxEwuJP8qAUus18snN599tXmtgYLU51QqUrJh+MC8+tlkWHj+x9VQMAV5jlAioq
d2aZPJg+cC2P+a9BB15c6j5Kyx3cYRJwHzKcr2G/nbvfGAL3ECr1CuC0My4ae9Rl
9OMzOkV9J/QIDZPBFNfZTjWCMDyCLG92F318GJ+vi2EquX+Qc6Z2aS3/5BITPX61
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
NDRhZjhhN2RkYzA5ODk4ZDUzMGMyFIAAAAAAEgAXcHJvb2ZAbWV0YWNvZGUuYml6
ZG5zOm5peG5ldC54eXo/dHlwZT1UWFQ8FIAAAAAAEgAhcHJvb2ZAbWV0YWNvZGUu
Yml6aHR0cHM6Ly9tYXN0by5uaXhuZXQueHl6L0BhbW9saXRoZBSAAAAAABIASXBy
b29mQG1ldGFjb2RlLmJpemh0dHBzOi8vd3d3LnJlZGRpdC5jb20vdXNlci9BbW9s
aXRoL2NvbW1lbnRzL2J4enJvei9ncGdfa2V5X3ZlcmlmaWNhdGlvbi8ACgkQUf1A
k22wBluVXA/+KMdsHcfNZEFRDXoCYxEA24PPqLcaObz7ounUBYdjuljpdi+prPWs
FT7AR214mC5UbOUtfCHrZ5bbkMD+Si6UDKoyiu8joZa6GKr5ddTkbdo0QJxQHCT+
cZAqLY097UCXKhHjwD71hma4FuWKBCNh6ix3XDP5vZ5rRVajZMTADFZP044mRH4O
Q+aW0vBhYaWgXa0BAnNhBw70lz/oHdM1zi8XqiB4pNBsmdHd3GbH7tIwCqbXw9gi
s/dFGeWIERdCLrxR+45akWJm+uSUlFbipGX/zBG/5oJYjPXnRU973n0mX5MWFd3a
vLJskoWyVBvrlKNKJqf6tU59umo2ocwEkKLtZJ0V3YG5lWF6dPA1svmpKvA/ufnc
T83PiJgZGBR+yTwGsoH3fMbsvAo1uS76+ZWo3ulYgMWEDuI4kI/rLxqd9Ya0e/tG
JVVuPtUWdx1+eebBSWTJU98KB+QKeaO52vIkUPsPFx8y029Dvx4TD7wK9jbzKJZB
uPDIQSQXaqH3LsbvsGIG3bkTlECIQlTZhFHg1M5SJENRzp2Z4GfLkv2KONQAPEkJ
BKcHKZYXZbK8hetpy74O+Jj2c8MSPUrrbI5iC8NwhcwF2gfkow8H/rAQhuEt2xRK
9zO9ISkOukLccyczlEb7hP1NKIoVSzJrN+E55PIMxjSr1jQXQ4SMRJi5Ag0EW/I8
OwEQALsWpBxmWOrcNOJjlAlqVW+JZS2MebKFnN0vC2sBzs0UyZcLGZCSMd3GxQM7
rIMbkcsmqF4lFs/gU2CEHALhJzCGvOsKHCiOevO/qwQy4bicMur8DwSD+N3ZA7sj
g5x9MiTJmYkmPUC9qKvq0ZVCK38fyD39MdtTCe+UYclOkXzc3dGHmwLzDYmmXpbj
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
OHc=
=nOej
-----END PGP PUBLIC KEY BLOCK-----

View File

@ -1,5 +1,5 @@
---
layout: page
layout: home
title: Contact
subtitle: Where to find me
description: Various ways to contact me
@ -11,6 +11,12 @@ These are some of my more public accounts; feel free to contact me at any of the
</p>
<div class="flex-wrapper">
<div class="flex-cards">
<div class="contact-card">
<a title="Jabber/XMPP" ref="me" href="xmpp:amolith@nixnet.xyz" target="_blank">
<h1><i class="fa fa-xmpp"></i></h1>
<p>Jabber/XMPP</p>
</a>
</div>
<div class="contact-card">
<a title="Email" href="mailto:{{ site.author.email }}" target="_blank">
<h1><i class="fa fa-envelope"></i></h1>
@ -18,21 +24,15 @@ These are some of my more public accounts; feel free to contact me at any of the
</a>
</div>
<div class="contact-card">
<a title="Telegram" href="https://t.me/amolith/" target="_blank">
<h1><i class="fa fa-telegram"></i></h1>
<p>Telegram</p>
</a>
</div>
<div class="contact-card">
<a title="Mastodon" rel="me" href="https://masto.nixnet.xyz/@amolith" target="_blank">
<a title="Mastodon" rel="me" rel="noreferrer" href="https://masto.nixnet.xyz/@amolith" target="_blank">
<h1><i class="fa fa-mastodon"></i></h1>
<p>Mastodon</p>
</a>
</div>
<div class="contact-card">
<a title="Keybase" ref="me" href="https://keybase.io/amolith" target="_blank">
<h1><i class="fa fa-keybase"></i></h1>
<p>Keybase</p>
<a title="Telegram" rel="noreferrer" href="https://t.me/amolith/" target="_blank">
<h1><i class="fa fa-telegram"></i></h1>
<p>Telegram</p>
</a>
</div>
</div>
@ -40,9 +40,10 @@ These are some of my more public accounts; feel free to contact me at any of the
<br/>
<br/>
<hr/>
<br/>
<div class="content">
<p class="center">
I also have <a href="https://briarproject.org/" target="_blank">Briar</a> if we meet IRL and I'm on <a href="https://wire.com/en/" target="_blank">Wire</a> as <code>@amolith</code>. I can be found on my XMPP server at <code>amolith@nixnet.xyz</code> as well.
I also have <a href="https://briarproject.org/" rel="noreferrer" target="_blank">Briar</a> if we meet IRL and I'm on <a href="https://wire.com/en/" rel="noreferrer" target="_blank">Wire</a> as <code>@amolith</code>.
</p>
<p class="center">
Despite the many ways to contact me, email and XMPP are and always will be my most preferrered methods (as well as the most reliable). If you email me, please be sure to encrypt it with my <a title="Plaintext GPG key" href="/amolith.txt" type="text/plain" target="_blank">GPG key</a>. If you message me over XMPP, please make sure it's with a client that has OMEMO encryption.

78
contact2.html Normal file
View File

@ -0,0 +1,78 @@
---
layout: page
title: Contact
subtitle: Where to find me
description: Various ways to contact me
cover: /assets/pages/contact.png
permalink: /contact2/
---
<style>
.props { list-style-type: none; margin-left: 0; padding-left: 0; }
i { padding-right: 5px; }
.proof { font-size: small; margin-left: 10px; color: #73a6ff }
.verification { font-size: small; margin-left: 5px; cursor: pointer }
summary { cursor: pointer }
.verified { color: green }
.verified::before { content: "✅"; margin-right: 5px; }
.avatar { width: 148px; height: 148px; border-radius: 74px;
display: block;
margin-left: auto;
margin-right: auto;
}
h2 { text-align: center; line-height: 1.5 }
.wrapper { margin: 40px 0; }
.wrapper > div { margin: 20px; }
textarea { width: 100%; height: 200px; }
.note { font-size: small }
@media (min-width: 600px) {
.wrapper {
display: flex;
width: 100%;
}
.wrapper .bio {
width: 35%;
}
}
</style>
<script>
var System = {
_deps: Object.create(null),
register(name, deps, callback) {
const exports = Object.create(null);
const result = callback((name, value) => exports[name] = value);
for (let i = 0; i < deps.length; i++) {
result.setters[i](this._deps[deps[i]]);
}
result.execute();
this._deps[name] = exports;
}
};
</script>
<style>
img { vertical-align: top }
</style>
<script src="/openpgp.js"></script>
<script src="/scripts.js"></script>
<body>
<header>
<div class="col cont">
<div class="left">
<a href="index.html">OpenPGP</a>
</div>
<div class="links">
<a href="../@wiktor.html">Contact</a>
</div>
</div>
</header>
<main>
<div class="col">
<section id="content">
<div id=result>Loading key...</div>
</section>
<section class="note">
<p>Note: contents of this page are generated purely from the OpenPGP key in your browser.
If you want to add social proofs to your key see <a href="proofs.html">OpenPGP Proofs</a> page.</p>
<p>If you want to adjust the keyserver used or the key being displayed just edit this HTML page.</p>
</section>
</div>

View File

@ -8,7 +8,7 @@ sitemap:
/* =Colors */
$dorian: #323234;
$iron: #ffffff;
$cloudy: #828282;
$cloudy: #9d9d9d;
@import
"mixins",

View File

@ -1,23 +0,0 @@
---
layout: page
title: Friends of NixNet
subtitle: A list of some like-minded people and their websites
description: A list of some like-minded people and their websites
cover: /assets/pages/friends.png
permalink: /friends/
---
<div class="content">
<h2>People</h2>
<ul>
<li><a href="https://lushka.al/">Anxhelo Lushka</a> - graphic designer, frontend developer, computer engineering student and heavy open source user/advocate. Has an interesting blog.</li>
<li><a href="http://lukesmith.xyz/">Luke Smith</a> - makes technology videos on YouTube, is the Luke of <a href="https://larbs.xyz/">Luke&#39;s Auto-Rice Bootstrapping Scripts (LARBS)</a>, and does a podcast called <em>Not Related</em> on &quot;Big-Braned&quot; topics</li>
</ul>
<h2>Organisations</h2>
<ul>
<li><a href="https://libreho.st/">LibreHo.st</a> - a network of average people who host FLOSS services available for anyone to use</li>
<li><a href="https://lelux.fi/">Lelux.fi</a> - really cool guy who hosts some services like I do</li>
<li><a href="https://snopyta.org/">Snopyta.org</a> - Snopyta provides online services based on freedom, privacy and decentralization. Part of LibreHosters.</li>
<li><a href="https://libredesigners.org/">LibreDesigners.org</a> - a website for learning how to create art, interfaces, websites, etc. with free/libre and open source software (Portuguese-only right now)</li>
<li><a href="https://cygonetwork.com">CYGONetwork.com</a> - alternative to Facebook. Better features, better community, and enhanced privacy/security</li>
</ul>
</div>

0
img.py Normal file → Executable file
View File

View File

@ -1,5 +1,5 @@
---
layout: page
layout: home
title: "NixNet"
subtitle: "Freedom served with a slice of liberty"
description: "A network of websites and services hosted by Amolith available for anyone to use free of charge."
@ -11,7 +11,7 @@ priority: 0.9
<p>I host a variety of services that are available for anyone to use free of charge. Below is a list with descriptions of each.
<br />
<br />
<a href="https://git.nixnet.xyz/NixNet" target="_blank"><button class="donate"><i class="fa fa-cogs"></i> Technical Info</button></a>
<a href="https://git.nixnet.xyz/NixNet" rel="noreferrer" target="_blank"><button class="donate"><i class="fa fa-cogs"></i> Technical Info</button></a>
</p>
</center>
<!--

View File

@ -6,13 +6,13 @@ description: A bit about NixNet's admin, Amolith
cover: /assets/pages/me.png
permalink: /me/
---
<p>I am an 18 year old student who lives in the Southern US. This is my last year in high school and Im planning to graduate with my high school diploma, an Associates Degree in Arts, a second in Sciences, and a third in Fine Arts, Music.</p>
<p>I am an 19 year old student who lives in the Southern US. This is my last year in high school and Im planning to graduate with my high school diploma, an Associates Degree in Arts, a second in Sciences, and a third in Fine Arts, Music.</p>
<center><h1>Experience with Linux, abbrv.</h1></center>
<center><h2>Where it all started</h2></center>
<h2>Where it all started</h2>
<p>I got started with GNU/Linux nearly two years ago and it was amazing. The only computer I had at the time was an Acer C710 Chromebook that I got at the beginning of 8th grade. I had this for three years before I grew tired of how limited it was. A friend told me about this thing called Linux and how I should look into seeing if I could get it on my Chromebook. He brought a USB stick to school that he said was “bootable”. I had no idea what this was but I trusted him. We turned off my Chromebook and turned it back on and he tried pressing a bunch of keys. This didnt do anything. He was really confused and told me Id have to do my own research on how to install Linux. I did and, eventually, I discovered a few tutorials I could follow. I combined a couple different ones, messed with the motherboard, enabled dev mode, flashed a new BIOS, and got vanilla Ubuntu installed.</p>
<center><h2>Distro hopping</h2></center>
<h2>Distro hopping</h2>
<p>I had a very bad experience with this because the Acer C710 has a 1.1 GHz dual-core processor, 2 GB of RAM, and 16 GB of storage (SSD). I didnt give up though and started distro hopping, looking for the most lightweight distro I could find. This eventually led me to GalliumOS, a distro built for Chromebooks. It ran well enough but I had heard of this thing called Arch that was supposed to be the ultimate. I knew I couldnt install vanilla Arch so I went with ArcoLinuxD (ArchMergeD, at the time) and it was a great experience. Thats whats still on my Chromebook.</p>
<center><h2>“Real” computer</h2></center>
<h2>“Real” computer</h2>
<p>Last March, a friends father got me a brand new laptop that actually works. I left Windows on it for three days then wiped it. I went with ArchLabs and loved it . . . until I tried to play some Steam games. Apparently there was a font issue with some of ArchLabs s fonts. No one was able to help so I just went for Arch. I installed Xubuntu (I like lightweight distros on powerful machines) on half the drive and worked on Arch for the other half. I tried and failed in two days the first time and succeeded in 15 minutes the next time. It took all the next day to get it set up. Im actually still on that same installation and haven't had anything break so far.</p>
<center><h1>That brings us to . . . now</h1>

42864
openpgp.js Normal file

File diff suppressed because one or more lines are too long

3
package-lock.json generated Normal file
View File

@ -0,0 +1,3 @@
{
"lockfileVersion": 1
}

35
privacy-policy.md Normal file
View File

@ -0,0 +1,35 @@
---
layout: page
title: Privacy Policy
description: I encourage you to read the whole document. It's not particularly long or difficult to understand.
subtitle: What's being done with your data?
permalink: /privacy/
cover: /assets/posts/privacy.png
---
# Privacy Policy
This will hopefully be the briefest "legal" document you've ever read as well as the most readable. If you need additional information [let me know](/contact) and I'll add it.
## IP Address
Some applications (Gitea, Mastodon, Mumble, XMPP) collect your IP when you register. At the moment, that information is kept indefinitely. However, I'm working on either completely disabling it or setting something up that will periodically delete stored IP addresses. When I do, this document will be updated accordingly.
If you don't want me to have that information to begin with, just use [Tor Browser](https://www.torproject.org/).
## Email Address
When you register for a service using an email address, that is obviously collected. You can control whether it's a real one or not. Even though I can see them for services like Gitea and Mastodon, I don't care and won't send you unsolicited mail.
**Note:** whatever address you use for git is visible in commits.
## Browser Fingerprint
Your web browser communicates uniquely identifying information to all websites it visits by allowing the site to know details about your operating system, browser information, plugins installed, fonts installed, screen resolution, and [much more](https://panopticlick.eff.org/). I don't care about that either and, if some services do collect that for their own use (I'm 99% sure none of them do), I'm not going to look at it ¯\\_(ツ)\_/¯
## Usage and storage of collected information
**For most services:** Whatever data is collected is stored on one server in Germany and won't be shared with any third parties whatsoever.
**For Nextcloud:** Whatever data is collected is stored on one server in my living room and won't be shared with any third parties either. User's files are encrypted at rest so no one can hack into my server and steal them. I do have the encryption key so I *could* decrypt and view your files. I'm not going to bother with that though because I don't have any interest in looking at your personal stuff. That's your business and I won't invade your privacy.
# Exceptions
I do live in the US; one server is here and the other is in Germany. If, for whatever reason, I'm compelled by law enforcement to give up your email, IP address, or any other information, I will. *I don't want to*. As such, I do whatever I can to make sure *I don't have that information*. If I don't have it, I can't share it.
# Recommendations
To mitigate invasions of privacy like this, use a throwaway email address for registration, such as one from [cock.li](https://cock.li/), or [ProtonMail](https://protonmail.com/), provide a [fake name](https://fakena.me/fake-name/), and use the service from behind [Tor](https://www.torproject.org/) or a VPN. Rather than a VPN, however, I *strongly* recommend using Tor across all devices. They have an [Android version](https://www.torproject.org/download/#android) now and there's another browser for iOS that they recommend called [Onion Browser](https://apps.apple.com/us/app/onion-browser/id519296448). I don't use iOS so I can't say whether or not it's any good, just that the Tor Project recommends it below the Android section.

1
protocol-handler.js Normal file
View File

@ -0,0 +1 @@
window.addEventListener("load",function(){var e=document.getElementById("register");e&&e.addEventListener("click",function(){navigator.registerProtocolHandler("openpgp4fpr","https://metacode.biz/openpgp/resolve/%s","Search for key on the keyserver")});var r=document.getElementById("search");r&&r.addEventListener("submit",function(t){t.preventDefault(),t.disabled=!0;var o=t.target.querySelector("ul");o.textContent="Checking OpenPGP key using Web Key Directory...";var e=t.target.querySelector("input").value;fetch("./wkd-checker",{method:"POST",body:JSON.stringify({email:e})}).then(function(e){return e.json()}).then(function(e){var r=[];r.push({category:"info",value:"Key address",url:e.key.url}),200!==e.key.code?r.push({category:"error",value:"Key not found"}):(r.push({category:"ok",value:"Key file found"}),e.key.response.startsWith("9")?r.push({category:"ok",value:"Key format correct"}):r.push({category:"error",value:"Key format error: key should be in binary form, not ASCII-armored"}),e.key.cors?(r.push({category:"ok",value:"Key is accessible from all sites"}),e["fake-key"].cors?r.push({category:"ok",value:"Not found keys also generate CORS headers"}):r.push({category:"warn",value:"Not found keys do not have CORS headers"})):r.push({category:"warn",value:"Key is not accessible, add 'Access-Control-Allow-Origin: *' header"})),200!==e.policy.code?r.push({category:"error",value:"Policy not found. Policy file can be empty",url:e.policy.url}):r.push({category:"ok",value:"Policy file found"}),o.innerHTML="",r.map(function(e){var r=document.createElement("LI");if(r.textContent=e.value,r.className=e.category,e.url){var t=document.createElement("A");t.href=e.url,t.textContent=e.url,t.target="_blank",t.setAttribute("rel","nofollow noopener"),r.textContent+=": ",r.appendChild(t)}return r}).forEach(o.appendChild.bind(o)),console.log(r),t.disabled=!1})})});

537
scripts.js Normal file
View File

@ -0,0 +1,537 @@
System.register("local", [], function (exports_1, context_1) {
"use strict";
var __moduleName = context_1 && context_1.id;
function createElement(name, attributes, ...children) {
return {
name,
attributes: attributes || {},
children: Array.prototype.concat(...(children || []))
};
}
exports_1("createElement", createElement);
return {
setters: [],
execute: function () {
}
};
});
System.register("renderer", [], function (exports_2, context_2) {
"use strict";
var __moduleName = context_2 && context_2.id;
function render(element) {
if (element == null)
return '';
if (typeof element !== "object")
element = String(element);
if (typeof element === "string")
return element.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
//if (element instanceof Raw) return element.html;
console.assert(!!element.attributes, 'Element attributes must be defined:\n' + JSON.stringify(element));
const elementAttributes = element.attributes;
let attributes = Object.keys(elementAttributes).filter(key => {
const value = elementAttributes[key];
return value != null;
}).map(key => {
const value = elementAttributes[key];
if (value === true) {
return key;
}
return `${key}="${String(value).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;')}"`;
}).join(' ');
if (attributes.length > 0) {
attributes = ' ' + attributes;
}
const children = element.children.length > 0 ? `>${element.children.map(child => render(child)).join('')}` : '>';
return `<${element.name}${attributes}${children}</${element.name}>`;
}
exports_2("render", render);
return {
setters: [],
execute: function () {
}
};
});
/*
Copyright 2019 Wiktor Kwapisiewicz
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
System.register("openpgp-key", ["local", "renderer"], function (exports_3, context_3) {
"use strict";
var local, renderer, proofs, dateFormat;
var __moduleName = context_3 && context_3.id;
function getLatestSignature(signatures, date = new Date()) {
let signature = signatures[0];
for (let i = 1; i < signatures.length; i++) {
if (signatures[i].created >= signature.created &&
(signatures[i].created <= date || date === null)) {
signature = signatures[i];
}
}
return signature;
}
function getVerifier(proofUrl, fingerprint) {
for (const proof of proofs) {
const matches = proofUrl.match(proof.matcher);
if (!matches)
continue;
const bound = Object.entries(proof.variables).map(([key, value]) => [key, matches[value || 0]]).reduce((previous, current) => { previous[current[0]] = current[1]; return previous; }, { FINGERPRINT: fingerprint });
const profile = proof.profile.replace(/\{([A-Z]+)\}/g, (_, name) => bound[name]);
const proofJson = proof.proof.replace(/\{([A-Z]+)\}/g, (_, name) => bound[name]);
const username = proof.username.replace(/\{([A-Z]+)\}/g, (_, name) => bound[name]);
return {
profile,
proofUrl,
proofJson,
username,
service: proof.service,
checks: (proof.checks || []).map((check) => ({
relation: check.relation,
proof: check.proof,
claim: check.claim.replace(/\{([A-Z]+)\}/g, (_, name) => bound[name])
}))
};
}
return null;
}
async function verify(proofJson, checks) {
const response = await fetch(proofJson, {
headers: {
Accept: 'application/json'
},
credentials: 'omit'
});
if (!response.ok) {
throw new Error('Response failed: ' + response.status);
}
const json = await response.json();
for (const check of checks) {
const proofValue = check.proof.reduce((previous, current) => {
if (current == null || previous == null)
return null;
if (Array.isArray(previous) && typeof current === 'string') {
return previous.map(value => value[current]);
}
return previous[current];
}, json);
const claimValue = check.claim;
if (check.relation === 'eq') {
if (proofValue !== claimValue) {
throw new Error(`Proof value ${proofValue} !== claim value ${claimValue}`);
}
}
else if (check.relation === 'contains') {
if (!proofValue || proofValue.indexOf(claimValue) === -1) {
throw new Error(`Proof value ${proofValue} does not contain claim value ${claimValue}`);
}
}
else if (check.relation === 'oneOf') {
if (!proofValue || proofValue.indexOf(claimValue) === -1) {
throw new Error(`Proof value ${proofValue} does not contain claim value ${claimValue}`);
}
}
}
}
function serviceToClassName(service) {
if (service === 'github') {
return 'fab fa-github';
}
else if (service === 'reddit') {
return 'fab fa-reddit';
}
else if (service === 'hackernews') {
return 'fab fa-hacker-news';
}
else if (service === 'mastodon') {
return 'fab fa-mastodon';
}
else if (service === 'dns') {
return 'fas fa-globe';
}
else {
return '';
}
}
async function lookupKey(query) {
const result = document.getElementById('result');
result.innerHTML = renderer.render(local.createElement("span", null,
"Looking up ",
query,
"..."));
let keys, keyUrl;
const keyLink = document.querySelector('[rel="pgpkey"]');
if (!keyLink) {
const keyserver = document.querySelector('meta[name="keyserver"]').content;
keyUrl = `https://${keyserver}/pks/lookup?op=get&options=mr&search=${query}`;
const response = await fetch(keyUrl);
const key = await response.text();
keys = (await openpgp.key.readArmored(key)).keys;
}
else {
keyUrl = keyLink.href;
const response = await fetch(keyUrl);
const key = await response.arrayBuffer();
keys = (await openpgp.key.read(new Uint8Array(key))).keys;
}
if (keys.length > 0) {
loadKeys(keyUrl, keys).catch(e => {
result.innerHTML = renderer.render(local.createElement("span", null,
"Could not display this key: ",
String(e)));
});
}
else {
result.innerHTML = renderer.render(local.createElement("span", null,
query,
": not found"));
}
}
async function loadKeys(keyUrl, _keys) {
const key = _keys[0];
window.key = key;
const primaryUser = await key.getPrimaryUser();
for (var i = key.users.length - 1; i >= 0; i--) {
try {
if (await key.users[i].verify(key.primaryKey) === openpgp.enums.keyStatus.valid) {
continue;
}
}
catch (e) {
console.error('User verification error:', e);
}
//key.users.splice(i, 1);
}
for (const user of key.users) {
user.revoked = await user.isRevoked();
}
const lastPrimarySig = primaryUser.selfCertification;
const keys = [{
fingerprint: key.primaryKey.getFingerprint(),
status: await key.verifyPrimaryKey(),
keyFlags: lastPrimarySig.keyFlags,
created: key.primaryKey.created,
algorithmInfo: key.primaryKey.getAlgorithmInfo(),
expirationTime: lastPrimarySig.getExpirationTime()
}];
//console.log(lastPrimarySig);
const proofs = (lastPrimarySig.notations || [])
.filter((notation) => notation[0] === 'proof@metacode.biz' && typeof notation[1] === 'string')
.map((notation) => notation[1])
.map((proofUrl) => getVerifier(proofUrl, key.primaryKey.getFingerprint()))
.filter((verifier) => !!verifier);
/*
proofs.push(getVerifier('https://www.reddit.com/user/wiktor-k/comments/bo5oih/test/', key.primaryKey.getFingerprint()));
proofs.push(getVerifier('https://news.ycombinator.com/user?id=wiktor-k', key.primaryKey.getFingerprint()));
proofs.push(getVerifier('https://gist.github.com/wiktor-k/389d589dd19250e1f9a42bc3d5d40c16', key.primaryKey.getFingerprint()));
proofs.push(getVerifier('https://metacode.biz/@wiktor', key.primaryKey.getFingerprint()));
proofs.push(getVerifier('dns:metacode.biz?type=TXT', key.primaryKey.getFingerprint()));
*/
for (const subKey of key.subKeys) {
const lastSig = getLatestSignature(subKey.bindingSignatures);
let reasonForRevocation;
if (subKey.revocationSignatures.length > 0) {
reasonForRevocation = subKey.revocationSignatures[subKey.revocationSignatures.length - 1].reasonForRevocationString;
}
keys.push({
fingerprint: subKey.keyPacket.getFingerprint(),
status: await subKey.verify(key.primaryKey),
reasonForRevocation,
keyFlags: lastSig.keyFlags,
created: lastSig.created,
algorithmInfo: subKey.keyPacket.getAlgorithmInfo(),
expirationTime: await subKey.getExpirationTime()
});
}
//key.users.splice(primaryUser.index, 1);
const profileHash = await openpgp.crypto.hash.md5(openpgp.util.str_to_Uint8Array(primaryUser.user.userId.email)).then((u) => openpgp.util.str_to_hex(openpgp.util.Uint8Array_to_str(u)));
const now = new Date();
// there is index property on primaryUser
document.title = primaryUser.user.userId.name + ' - OpenPGP key';
const info = local.createElement("div", null,
local.createElement("div", { class: "wrapper" },
local.createElement("div", { class: "bio" },
local.createElement("img", { class: "avatar", src: "https://seccdn.libravatar.org/avatar/" + profileHash + "?s=148&d=" + encodeURIComponent("https://www.gravatar.com/avatar/" + profileHash + "?s=148&d=mm") }),
local.createElement("h2", null, primaryUser.user.userId.name)),
local.createElement("div", null,
local.createElement("ul", { class: "props" },
local.createElement("li", { title: key.primaryKey.getFingerprint() },
local.createElement("a", { href: keyUrl, target: "_blank", rel: "nofollow noopener" },
"\uD83D\uDD11\u00A0",
local.createElement("code", null, key.primaryKey.getFingerprint()))),
key.users.filter((user) => !user.revoked && user.userId).map((user) => user.userId.email).filter((email) => !!email).map((email) => local.createElement("li", null,
local.createElement("a", { href: "mailto:" + email },
"\uD83D\uDCE7 ",
email
//formatAttribute(user.userAttribute)
))),
proofs.filter((proof) => !!proof).map((proof) => local.createElement("li", null,
local.createElement("a", { rel: "me noopener nofollow", target: "_blank", href: proof.profile },
local.createElement("i", { class: serviceToClassName(proof.service) }),
proof.username),
local.createElement("a", { rel: "noopener nofollow", target: "_blank", href: proof.proofUrl, class: "proof", "data-proof-json": proof.proofJson, "data-checks": JSON.stringify(proof.checks) },
local.createElement("i", { class: "fas fa-certificate" }),
"proof")))))),
local.createElement("details", null,
local.createElement("summary", null, "\uD83D\uDD12 Encrypt"),
local.createElement("textarea", { placeholder: "Message to encrypt...", id: "message" }),
local.createElement("input", { type: "button", value: "Encrypt", id: "encrypt" }),
' ',
local.createElement("input", { type: "button", id: "send", "data-recipient": primaryUser.user.userId.email, value: "Send to " + primaryUser.user.userId.email })),
local.createElement("details", null,
local.createElement("summary", null, "\uD83D\uDD8B Verify"),
local.createElement("textarea", { placeholder: "Clearsigned message to verify...", id: "signed" }),
local.createElement("input", { type: "button", value: "Verify", id: "verify" })),
local.createElement("details", null,
local.createElement("summary", null, "\uD83D\uDD11 Key details"),
local.createElement("p", null, "Subkeys:"),
local.createElement("ul", null, keys.map((subKey) => local.createElement("li", null,
local.createElement("div", null,
getStatus(subKey.status, subKey.reasonForRevocation),
" ",
getIcon(subKey.keyFlags),
" ",
local.createElement("code", null, subKey.fingerprint.substring(24).match(/.{4}/g).join(" ")),
" ",
formatAlgorithm(subKey.algorithmInfo.algorithm),
" (",
subKey.algorithmInfo.bits,
")"),
local.createElement("div", null,
"created: ",
formatDate(subKey.created),
", expire",
now > subKey.expirationTime ? "d" : "s",
": ",
formatDate(subKey.expirationTime)))))));
document.getElementById('result').innerHTML = renderer.render(info);
checkProofs();
}
async function checkProofs() {
const proofs = document.querySelectorAll('[data-checks]');
for (const proofLink of proofs) {
const checks = JSON.parse(proofLink.dataset.checks || '');
const url = proofLink.dataset.proofJson || '';
try {
await verify(url, checks);
proofLink.textContent = 'verified proof';
proofLink.classList.add('verified');
}
catch (e) {
console.error('Could not verify proof: ' + e);
}
}
}
async function verifyProof(e) {
const target = e.target;
if (target.id === 'encrypt') {
const text = document.getElementById('message');
openpgp.encrypt({
message: openpgp.message.fromText(text.value),
publicKeys: [window.key],
armor: true
}).then((cipherText) => {
text.value = cipherText.data;
}, (e) => alert(e));
}
else if (target.id === 'send') {
location.href = "mailto:" + target.dataset.recipient + "?subject=Encrypted%20message&body=" + encodeURIComponent(document.getElementById('message').value);
}
else if (target.id === 'verify') {
const text = document.getElementById('signed');
const message = await openpgp.cleartext.readArmored(text.value);
const verified = await openpgp.verify({
message,
publicKeys: [window.key]
});
console.log(verified);
alert('The signature is ' + (verified.signatures[0].valid ? '✅ correct.' : '❌ incorrect.'));
}
}
function formatAttribute(userAttribute) {
if (userAttribute.attributes[0][0] === String.fromCharCode(1)) {
return local.createElement("img", { src: "data:image/jpeg;base64," + btoa(userAttribute.attributes[0].substring(17)) });
}
if (userAttribute.attributes[0][0] === 'e') {
const url = userAttribute.attributes[0].substring(userAttribute.attributes[0].indexOf('@') + 1);
return local.createElement("a", { href: url, rel: "noopener nofollow" }, url);
}
return 'unknown attribute';
}
function formatAlgorithm(name) {
if (name === 'rsa_encrypt_sign')
return "RSA";
return name;
}
function formatDate(date) {
if (date === Infinity)
return "never";
if (typeof date === 'number')
return 'x';
return dateFormat.format(date);
}
function getStatus(status, details) {
if (status === openpgp.enums.keyStatus.invalid) {
return local.createElement("span", { title: "Invalid key" }, "\u274C");
}
if (status === openpgp.enums.keyStatus.expired) {
return local.createElement("span", { title: "Key expired" }, "\u23F0");
}
if (status === openpgp.enums.keyStatus.revoked) {
return local.createElement("span", { title: "Key revoked: " + details }, "\u274C");
}
if (status === openpgp.enums.keyStatus.valid) {
return local.createElement("span", { title: "Valid key" }, "\u2705");
}
if (status === openpgp.enums.keyStatus.no_self_cert) {
return local.createElement("span", { title: "Key not certified" }, "\u274C");
}
return "unknown:" + status;
}
function getIcon(keyFlags) {
if (!keyFlags || !keyFlags[0]) {
return "";
}
let flags = [];
if ((keyFlags[0] & openpgp.enums.keyFlags.certify_keys) !== 0) {
flags.push(local.createElement("span", { title: "Certyfing key" }, "\uD83C\uDFF5\uFE0F"));
}
if ((keyFlags[0] & openpgp.enums.keyFlags.sign_data) !== 0) {
flags.push(local.createElement("span", { title: 'Signing key' }, "\uD83D\uDD8B"));
}
if (((keyFlags[0] & openpgp.enums.keyFlags.encrypt_communication) !== 0) ||
((keyFlags[0] & openpgp.enums.keyFlags.encrypt_storage) !== 0)) {
flags.push(local.createElement("span", { title: 'Encryption key' }, "\uD83D\uDD12"));
}
if ((keyFlags[0] & openpgp.enums.keyFlags.authentication) !== 0) {
flags.push(local.createElement("span", { title: 'Authentication key' }, "\uD83D\uDCB3"));
}
return flags;
}
return {
setters: [
function (local_1) {
local = local_1;
},
function (renderer_1) {
renderer = renderer_1;
}
],
execute: function () {
openpgp.config.show_version = false;
openpgp.config.show_comment = false;
proofs = [
{
matcher: /^https:\/\/gist\.github\.com\/([A-Za-z0-9_-]+)\/([0-9a-f]+)$/,
variables: {
USERNAME: 1,
PROOFID: 2
},
profile: 'https://github.com/{USERNAME}',
proof: 'https://api.github.com/gists/{PROOFID}',
username: '{USERNAME}',
service: 'github',
checks: [{
relation: 'eq',
proof: ['owner', 'login'],
claim: '{USERNAME}'
}, {
relation: 'eq',
proof: ['owner', 'html_url'],
claim: 'https://github.com/{USERNAME}'
}, {
relation: 'contains',
proof: ['files', 'openpgp.md', 'content'],
claim: '[Verifying my OpenPGP key: openpgp4fpr:{FINGERPRINT}]'
}]
},
{
matcher: /^https:\/\/news\.ycombinator\.com\/user\?id=([A-Za-z0-9-]+)$/,
variables: {
USERNAME: 1,
PROFILE: 0
},
profile: '{PROFILE}',
proof: 'https://hacker-news.firebaseio.com/v0/user/{USERNAME}.json',
username: '{USERNAME}',
service: 'hackernews',
checks: [{
relation: 'contains',
proof: ['about'],
claim: '[Verifying my OpenPGP key: openpgp4fpr:{FINGERPRINT}]'
}]
},
{
matcher: /^https:\/\/www\.reddit\.com\/user\/([^/]+)\/comments\/([^/]+)\/([^/]+\/)?$/,
variables: {
USERNAME: 1,
PROOF: 2
},
profile: 'https://www.reddit.com/user/{USERNAME}',
proof: 'https://www.reddit.com/user/{USERNAME}/comments/{PROOF}.json',
username: '{USERNAME}',
service: 'reddit',
checks: [{
relation: 'contains',
proof: [0, 'data', 'children', 0, 'data', 'selftext'],
claim: 'Verifying my OpenPGP key: openpgp4fpr:{FINGERPRINT}'
}, {
relation: 'eq',
proof: [0, 'data', 'children', 0, 'data', 'author'],
claim: '{USERNAME}'
}]
},
{
matcher: /^https:\/\/([^/]+)\/@([A-Za-z0-9_-]+)$/,
variables: {
INSTANCE: 1,
USERNAME: 2,
PROFILE: 0
},
profile: '{PROFILE}',
proof: '{PROFILE}',
username: '@{USERNAME}@{INSTANCE}',
service: 'mastodon',
checks: [{
relation: 'oneOf',
proof: ['attachment', 'value'],
claim: '{FINGERPRINT}'
}]
},
{
matcher: /^dns:([^?]+)\?type=TXT$/,
variables: {
DOMAIN: 1
},
profile: 'https://{DOMAIN}',
proof: 'https://dns.google.com/resolve?name={DOMAIN}&type=TXT',
username: '{DOMAIN}',
service: 'dns',
checks: [{
relation: 'oneOf',
proof: ['Answer', 'data'],
claim: '\"openpgp4fpr:{FINGERPRINT}\"'
}]
}
];
window.onload = window.onhashchange = function () {
lookupKey(location.hash.substring(1));
};
;
document.addEventListener('click', verifyProof);
dateFormat = new Intl.DateTimeFormat(undefined, {
year: 'numeric', month: 'numeric', day: 'numeric',
hour: 'numeric', minute: 'numeric', second: 'numeric',
});
}
};
});

4
verification.txt Normal file
View File

@ -0,0 +1,4 @@
This file claims ownership of the OpenPGP key with long id 0x51fd40936db0065b.
Token for proof:
[Verifying my OpenPGP key: openpgp4fpr:75dd32ca1bfeea6ae40d823c51fd40936db0065b]