aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Cleberg <hello@cleberg.net>2025-07-07 09:42:46 -0500
committerGitHub <noreply@github.com>2025-07-07 09:42:46 -0500
commite41732049217099644482e89ea5d3bc83eac63c7 (patch)
treeb014c037e61b1c16eef2efab01e7bde9f16d5b21
parent1716be666d7b8f19f3f4fdf345c42a997cc176bd (diff)
parent444ec6a63a1ffe94c6ffb5e6aa7fc8cdcc81dbb9 (diff)
downloadcleberg.net-e41732049217099644482e89ea5d3bc83eac63c7.tar.gz
cleberg.net-e41732049217099644482e89ea5d3bc83eac63c7.tar.bz2
cleberg.net-e41732049217099644482e89ea5d3bc83eac63c7.zip
Merge pull request #1 from ccleberg/theme-enhancements
Theme enhancements
-rw-r--r--build.py13
-rw-r--r--content/blog/2025-06-27-how-blockchain-works.org197
-rw-r--r--theme/static/styles.css210
-rw-r--r--theme/templates/base.html3
4 files changed, 370 insertions, 53 deletions
diff --git a/build.py b/build.py
index 59118fb..ee947f3 100644
--- a/build.py
+++ b/build.py
@@ -115,6 +115,7 @@ def get_recent_posts_html(content_dir="./content/blog", num_posts=3):
"date": re.compile(r"^#\+date:\s*<(\d{4}-\d{2}-\d{2})"),
"slug": re.compile(r"^#\+slug:\s*(.+)$", re.IGNORECASE),
"filetags": re.compile(r"^#\+filetags:\s*(.+)$", re.IGNORECASE),
+ "draft": re.compile(r"^#\+draft:\s*(.+)$", re.IGNORECASE),
}
for org_path in Path(content_dir).glob("*.org"):
@@ -122,6 +123,7 @@ def get_recent_posts_html(content_dir="./content/blog", num_posts=3):
date_str = None
slug = None
tags = []
+ is_draft = False
with org_path.open("r", encoding="utf-8") as f:
for line in f:
@@ -153,10 +155,21 @@ def get_recent_posts_html(content_dir="./content/blog", num_posts=3):
tags = [t for t in raw.split(":") if t]
continue
+ m = header_patterns["draft"].match(line)
+ if m:
+ draft_value = m.group(1).strip().lower()
+ if draft_value != "nil":
+ is_draft = True
+ break
+ continue
+
# Stop scanning once we have all required fields
if title and date_str and slug and tags:
break
+ if is_draft:
+ continue
+
if title and date_str and slug:
try:
date_obj = datetime.strptime(date_str, "%Y-%m-%d")
diff --git a/content/blog/2025-06-27-how-blockchain-works.org b/content/blog/2025-06-27-how-blockchain-works.org
new file mode 100644
index 0000000..c31e5a8
--- /dev/null
+++ b/content/blog/2025-06-27-how-blockchain-works.org
@@ -0,0 +1,197 @@
+#+date: <2025-07-07 Mon 00:00:00>
+#+title: Blockchain Series #1: How Blockchain Works Under the Hood: Hashes, Keys, and Signatures Explained
+#+description: Dive into blockchain's cryptographic foundations. Explore how hash functions, Merkle trees, and digital signatures secure distributed, tamper-resistant ledgers.
+#+slug: how-blockchain-works
+#+filetags: :blockchain:encryption:
+#+draft: t
+
+/This is Part 1 of a series I'm writing on blockchain. Stay tuned for further
+editions./
+
+Blockchain is one of those technologies that seems to generate more marketing
+buzz than real understanding. Everywhere you look, people talk about
+decentralization, trustless systems, and the next big disruption. But beneath
+the hype, blockchain systems rely on well-understood cryptographic building
+blocks to do something very specific: maintain a secure, tamper-resistant ledger
+without needing a central authority.
+
+If you're serious about understanding blockchain, it's critical to understand
+the cryptographic primitives that make it work. Hash functions, digital
+signatures, and public-key cryptography aren't just jargon—they're the core
+mechanisms that let a distributed network agree on a shared history no one can
+easily rewrite.
+
+This post is Part 1 of a multi-part series on blockchain. Here, we'll focus on
+these fundamental building blocks—how they work, why they're used, and how they
+fit together to provide the security and trust that blockchain promises.
+
+* What is Blockchain?
+
+At its core, a blockchain is a distributed, append-only ledger shared among
+participants in a network.
+
+What does this mean? Essentially, we can think of a standard, non-technical
+ledger (book of accounts where transactions are recorded against accounts). When
+introductin the idea of a blockchain, let's extend the idea of a standard ledger
+and make a few connections:
+
+- Each block of transactions is connected cryptographically to the block before
+ it, via a [[https://en.wikipedia.org/wiki/Cryptographic_hash_function][cryptographic hash]]. This is what forms a =chain= of blocks, or
+ records.
+- Each block consists of:
+ - A list of validated transactions
+ - A timestamp
+ - A cryptographic hash of the previous block (ensuring immutability)
+- Each transaction within a block is initiated between addresses, signed with
+ cryptographic keys, and sent to the blockchain for validation (e.g.,
+ proof-of-work, proof-of-staking, etc.).
+- The blockchain is shared amongst nodes in the network, who agree on the state
+ of the blockchain through consensus mechanisms.
+
+As we can see, the decentralized nature and cryptographic linking of
+transactions and blocks ensures that modifying the history is infeasible.
+
+If you're more of a visual person, here's a very basic diagram of a standard
+blockchain structure.
+
+#+begin_example
++------------+ +------------+ +------------+
+| Block 1 | -> | Block 2 | -> | Block 3 |
+|------------| |------------| |------------|
+| Data | | Data | | Data |
+| Prev Hash: | | Prev Hash: | | Prev Hash: |
+| 00000000 | | <hash1> | | <hash2> |
+| Hash: | | Hash: | | Hash: |
+| <hash1> | | <hash2> | | <hash3> |
++------------+ +------------+ +------------+
+#+end_example
+
+* What Problems is Blockchain Trying to Solve?
+
+I will be diving into the technical details of blockchains later in this post,
+but what exactly is the reason blockchain exists?
+
+You may know of cryptocurrencies, such as Bitcoin, but that is only one of many
+use cases for blockchains.
+
+As we learned in the section above, a blockchain can be equated to a ledger.
+With this in mind, let's dive into a few interesting use cases:
+
+** Immutable record-keeping
+
+If you simply need a ledger that cannot be modified easily and can establish a
+decentralized network to support that, blockchain is a great technology.
+
+** Trust without central authority
+
+The use of a decentralized system means that we do not need to rely on a
+centralized authority (e.g., Social Security, a bank, etc.) to store and provide
+access to information you need to record.
+
+Think of the US Social Security Number (SSN) system. Each time you want to
+perform actions that require verifying your identify (e.g., opening bank
+accounts, investment accounts, child birth, etc.), you are currently required to
+provide your SSN.
+
+However, this is a singular number - which means that if someone learns it, they
+can (essentially) now act as you.
+
+Now imagine a scenario where the SSN system is a blockchain where you have both
+your private key for providing evidence to people that you are you. For example,
+you open a bank account and sign your form with your private key. Now, the bank
+can take that and use your public key to decrypt the message and verify that you
+are you, without needing to know your private key.
+
+Another scenario is that, during a background check, a company could use your
+public key and consult the related blockchain to validate specific pieces of
+information. For example, if your identity alone is in one block, you could
+provide that information to your employer without providing your full SSN and
+all related personal information for as long as they keep your SSN on file.
+
+** Double-spending problem
+
+With the introduction of digital assets, such as cryptocurrencies and
+non-fungible tokens, a new risk is introduced: without control, these assets
+could be copied and reused at-will.
+
+To solve this problem, digital assets are transacted on a blockchain to ensure
+that the decentralized system of nodes provide consensus on validating
+transactions, transactions are recorded in a transparent and tamper-resistant
+manner, and cryptographic functions are performed to order the transactions
+logically on chain.
+
+* The Role of Cryptography in Blockchain
+- Why cryptography matters
+- Confidentiality vs. integrity/authenticity
+- Core goals:
+ - Tamper-evidence
+ - Secure identification
+ - Non-repudiation
+
+* Hash Functions
+- What is a cryptographic hash?
+- Properties:
+ - Collision resistance
+ - Pre-image resistance
+- How blockchain uses hashes:
+ - Chaining blocks together
+ - Block headers
+ - Transactions
+- Example command:
+ #+begin_src bash
+ echo -n "Hello, Blockchain" | sha256sum
+ #+end_src
+- Optional diagram: chain of blocks with hashes
+
+* Merkle Trees
+- Summarizing many transactions in a single root hash
+- Use case: efficient inclusion proofs
+- Example diagram (ASCII art if desired)
+- Why Merkle roots are in block headers
+
+* Public Key Cryptography
+- Quick refresher
+- Public/private keypairs
+- Addresses derived from public keys
+- Importance of keeping private keys secret
+
+* Digital Signatures
+- Purpose: proving authorship without revealing private key
+- Mention ECDSA / EdDSA
+- How transactions are signed
+- Example snippet:
+ #+begin_example
+ Alice signs transaction with her private key
+ → Anyone can verify with her public key
+ #+end_example
+- Why signatures prevent forgery
+
+* Bringing it All Together: Blockchain Data Structures
+- Block structure:
+ - Block header with previous block's hash
+ - Merkle root
+ - Timestamp, nonce
+- How the chain ensures immutability
+- Example flow:
+ 1. User creates a transaction
+ 2. Signs it
+ 3. Transaction included in block
+ 4. Block hash links to previous block
+
+* Proof of Work (Optional)
+- Hash puzzles to add blocks
+- Why it's hard to modify history
+- Keep this section simple
+
+* Conclusion
+- Summarize how these primitives work together
+- Tease next post: "Next, we'll explore security threats and how blockchain
+ networks mitigate them."
+- Optional links to further reading:
+ - Bitcoin whitepaper
+ - Ethereum docs
+ - Cryptography references
+
+* Optional Extras
+- Glossary box with terms (hash, signature, Merkle tree)
+- External references (e.g., NIST docs on hashes)
diff --git a/theme/static/styles.css b/theme/static/styles.css
index d21b23f..9de0c4f 100644
--- a/theme/static/styles.css
+++ b/theme/static/styles.css
@@ -9,8 +9,10 @@
*/
html {
- line-height: 1.15; /* 1 */
- -webkit-text-size-adjust: 100%; /* 2 */
+ line-height: 1.15;
+ /* 1 */
+ -webkit-text-size-adjust: 100%;
+ /* 2 */
}
/* Sections
@@ -43,9 +45,12 @@ h1 {
*/
hr {
- box-sizing: content-box; /* 1 */
- height: 0; /* 1 */
- overflow: visible; /* 2 */
+ box-sizing: content-box;
+ /* 1 */
+ height: 0;
+ /* 1 */
+ overflow: visible;
+ /* 2 */
}
/* Text-level semantics
@@ -65,9 +70,12 @@ a {
*/
abbr[title] {
- border-bottom: none; /* 1 */
- text-decoration: underline; /* 2 */
- text-decoration: underline dotted; /* 2 */
+ border-bottom: none;
+ /* 1 */
+ text-decoration: underline;
+ /* 2 */
+ text-decoration: underline dotted;
+ /* 2 */
}
/**
@@ -121,10 +129,14 @@ input,
optgroup,
select,
textarea {
- font-family: inherit; /* 1 */
- font-size: 100%; /* 1 */
- line-height: 1.15; /* 1 */
- margin: 0; /* 2 */
+ font-family: inherit;
+ /* 1 */
+ font-size: 100%;
+ /* 1 */
+ line-height: 1.15;
+ /* 1 */
+ margin: 0;
+ /* 2 */
}
/**
@@ -199,12 +211,18 @@ fieldset {
*/
legend {
- box-sizing: border-box; /* 1 */
- color: inherit; /* 2 */
- display: table; /* 1 */
- max-width: 100%; /* 1 */
- padding: 0; /* 3 */
- white-space: normal; /* 1 */
+ box-sizing: border-box;
+ /* 1 */
+ color: inherit;
+ /* 2 */
+ display: table;
+ /* 1 */
+ max-width: 100%;
+ /* 1 */
+ padding: 0;
+ /* 3 */
+ white-space: normal;
+ /* 1 */
}
/**
@@ -230,8 +248,10 @@ textarea {
[type="checkbox"],
[type="radio"] {
- box-sizing: border-box; /* 1 */
- padding: 0; /* 2 */
+ box-sizing: border-box;
+ /* 1 */
+ padding: 0;
+ /* 2 */
}
/**
@@ -249,8 +269,10 @@ textarea {
*/
[type="search"] {
- -webkit-appearance: textfield; /* 1 */
- outline-offset: -2px; /* 2 */
+ -webkit-appearance: textfield;
+ /* 1 */
+ outline-offset: -2px;
+ /* 2 */
}
/**
@@ -267,8 +289,10 @@ textarea {
*/
::-webkit-file-upload-button {
- -webkit-appearance: button; /* 1 */
- font: inherit; /* 2 */
+ -webkit-appearance: button;
+ /* 1 */
+ font: inherit;
+ /* 2 */
}
/* Misc
@@ -316,11 +340,21 @@ body {
Liberation Mono,
Lucida Console,
monospace;
- font-size: 0.9rem;
+ font-size: clamp(0.95rem, 1vw + 0.5rem, 1.1rem);
line-height: 1.5;
max-width: 50em;
margin: 0 auto;
- padding: 0 1rem;
+ padding: 0 clamp(1rem, 5vw, 3rem);
+}
+
+@media (min-width: 768px) {
+ body {
+ padding: 0 2rem;
+ }
+}
+
+main>*+* {
+ margin-top: 2rem;
}
.site-nav,
@@ -329,7 +363,7 @@ footer {
}
footer {
- border-top: 1px dotted;
+ /* border-top: 1px dotted; */
padding-top: 1rem;
margin: 1rem 0;
}
@@ -342,9 +376,9 @@ ul {
list-style-type: "- ";
}
-.site-nav {
+/* .site-nav {
border-bottom: 1px dotted;
-}
+} */
.site-nav ul {
list-style-type: none;
@@ -362,12 +396,43 @@ h2,
h3,
h4 {
color: var(--fg);
+ text-transform: uppercase;
+}
+
+h1 {
+ font-size: 2rem;
+ font-weight: bold;
+ /* border-bottom: 1px solid var(--border); */
+ margin-top: 2rem;
+ margin-bottom: 1rem;
+}
+
+h2 {
+ font-size: 1.5rem;
+ margin-top: 1.5rem;
+ margin-bottom: .75rem;
+}
+
+h3 {
+ font-size: 1.25rem;
+ margin-top: 1.25rem;
+ margin-bottom: .5rem;
+}
+
+#text-table-of-contents li {
+ text-transform: uppercase;
}
a,
a:visited {
color: var(--link);
- text-decoration: none;
+ text-decoration: underline;
+ text-decoration-skip-ink: auto;
+}
+
+a:focus-visible {
+ outline: 2px solid var(--link);
+ outline-offset: 2px;
}
a:hover {
@@ -393,7 +458,7 @@ table {
Liberation Mono,
Lucida Console,
monospace;
- font-size: 0.9rem;
+ font-size: inherit;
width: 100%;
}
@@ -406,7 +471,7 @@ td {
}
pre,
-pre > code,
+pre>code,
time,
code {
font-family:
@@ -426,7 +491,7 @@ pre {
overflow-x: auto;
}
-:not(pre) > code {
+:not(pre)>code {
color: var(--code);
font-family: inherit;
}
@@ -471,8 +536,8 @@ blockquote p {
}
.post-metadata {
- border: 1px dotted var(--fg);
- border-top: none;
+ border: 1px dotted var(--border);
+ /* border-top: none; */
padding: 1rem;
}
@@ -526,39 +591,80 @@ span.tag::before {
}
.post {
- display: flex;
- flex-direction: row;
- margin-bottom: 1rem;
+ display: flex;
+ flex-direction: row;
+ margin-bottom: 1rem;
}
.post-content {
- display: flex;
- flex-direction: column;
+ display: flex;
+ flex-direction: column;
}
.post-tags {
- font-size: 0.75rem;
- color: #999;
- margin-top: 0.1rem;
+ font-size: 0.85rem;
+ color: #999;
+ margin-top: 0.1rem;
}
.tag {
- margin-right: 0.3rem;
- font-style: normal;
- opacity: 0.8;
+ margin-right: 0.3rem;
+ font-style: normal;
+ opacity: 0.8;
}
.tag::before {
- content: "#";
+ content: "#";
+}
+
+.skip-link {
+ position: absolute;
+ left: -999px;
+ top: auto;
+ width: 1px;
+ height: 1px;
+ overflow: hidden;
+}
+
+.skip-link:focus {
+ left: 1rem;
+ top: 1rem;
+ width: auto;
+ height: auto;
+ background: var(--bg-bright);
+ color: var(--fg);
+ padding: .5rem;
+ border: 1px solid var(--fg);
}
@media (prefers-color-scheme: dark) {
:root {
- --bg: #141617;
- --bg-bright: #191c1d;
- --fg: #b2aea9;
- --link: gold;
- --code: red;
+ --bg: #121212;
+ --bg-bright: #1e1e1e;
+ --fg: #e0e0e0;
+ --link: #8ab4f8;
+ --code: #f28b82;
--border: #333;
}
}
+
+@media print {
+ body {
+ background: #fff;
+ color: #000;
+ font-size: 12pt;
+ padding: 0;
+ max-width: none;
+ }
+
+ .site-nav,
+ footer,
+ aside {
+ display: none;
+ }
+
+ a::after {
+ content: " (" attr(href) ")";
+ font-size: 90%;
+ }
+} \ No newline at end of file
diff --git a/theme/templates/base.html b/theme/templates/base.html
index daa43d0..6867ec7 100644
--- a/theme/templates/base.html
+++ b/theme/templates/base.html
@@ -17,6 +17,7 @@
{% endblock %}
</head>
<body>
+ <a href="#main" class="skip-link">Skip to content</a>
<nav class="site-nav" aria-label="site-nav" role="navigation">
<ul>
<li><a href="/">Home</a></li>
@@ -25,7 +26,7 @@
<li><a href="/wiki/">Wiki</a></li>
</ul>
</nav>
- <main>{% block main %}{% endblock %}</main>
+ <main id="main">{% block main %}{% endblock %}</main>
<footer>
<p>Donate: <a href="monero:82frXv83WVsGbTwuqSyb27cvy67JpD7Ktaij12Avy6ogfZatsgPG67YgsmEmvTFLKd1Rk7MUwx8D31ieGwLdD4wa4KdtxDB">XMR</a>
| <a href="ethereum:0x11255046Ccd637f1ACc78ae7c8849870f85638B3">ETH</a>