From 1a5f5622f2cc0e70e3c0775e64871e8a07d0eeaf Mon Sep 17 00:00:00 2001 From: Kyren223 Date: Fri, 15 Nov 2024 12:02:08 +0200 Subject: More changes to the way blogs looks and minor blog tweaks --- astro.config.mjs | 4 + package.json | 5 +- pnpm-lock.yaml | 103 ++++++++++++++++++ .../blogs/the-search-for-the-perfect-ssh-key.md | 118 --------------------- .../blogs/the-search-for-the-perfect-ssh-key.mdx | 117 ++++++++++++++++++++ src/pages/blogs/[...slug].astro | 53 +++++++-- tailwind.config.mjs | 4 - 7 files changed, 271 insertions(+), 133 deletions(-) delete mode 100644 src/content/blogs/the-search-for-the-perfect-ssh-key.md create mode 100644 src/content/blogs/the-search-for-the-perfect-ssh-key.mdx diff --git a/astro.config.mjs b/astro.config.mjs index 03cc6e0..e437788 100644 --- a/astro.config.mjs +++ b/astro.config.mjs @@ -16,6 +16,10 @@ export default defineConfig({ defaultProps: { showLineNumbers: false, }, + styleOverrides: { + borderColor: ({ theme }) => theme.colors["editor.background"], + borderRadius: "0", + }, }), mdx(), ], diff --git a/package.json b/package.json index b9b56bf..4d4f058 100644 --- a/package.json +++ b/package.json @@ -11,18 +11,15 @@ }, "dependencies": { "@astrojs/mdx": "^3.1.9", - "@astrojs/starlight": "^0.29.0", "@astrojs/tailwind": "^5.1.2", "@expressive-code/plugin-line-numbers": "^0.38.3", "astro": "^4.16.10", "astro-expressive-code": "^0.38.3", - "chart.js": "^4.4.6", "tailwindcss": "^3.4.14" }, "devDependencies": { - "@tailwindcss/typography": "^0.5.15", "prettier": "^3.3.3", "prettier-plugin-astro": "^0.14.1", "typescript": "^5.6.3" } -} \ No newline at end of file +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b12ccfd..e1f3a9c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8,6 +8,9 @@ importers: .: dependencies: + '@astrojs/markdoc': + specifier: ^0.11.5 + version: 0.11.5(astro@4.16.10(rollup@4.24.4)(typescript@5.6.3)) '@astrojs/mdx': specifier: ^3.1.9 version: 3.1.9(astro@4.16.10(rollup@4.24.4)(typescript@5.6.3)) @@ -62,6 +65,12 @@ packages: '@astrojs/internal-helpers@0.4.1': resolution: {integrity: sha512-bMf9jFihO8YP940uD70SI/RDzIhUHJAolWVcO1v5PUivxGKvfLZTLTVVxEYzGYyPsA3ivdLNqMnL5VgmQySa+g==} + '@astrojs/markdoc@0.11.5': + resolution: {integrity: sha512-paNSvJgUgld5kSU4RZelHYgvNKZSMWX2QX7SzWEeyPBTQ8gwOe30eJjq3czIbg7Se+8NcGtq7v5FU7lOyXxmnw==} + engines: {node: ^18.17.1 || ^20.3.0 || >=21.0.0} + peerDependencies: + astro: ^3.0.0 || ^4.0.0 + '@astrojs/markdown-remark@5.3.0': resolution: {integrity: sha512-r0Ikqr0e6ozPb5bvhup1qdWnSPUvQu6tub4ZLYaKyG50BXZ0ej6FhGz3GpChKpH7kglRFPObJd/bDyf2VM9pkg==} @@ -470,6 +479,18 @@ packages: '@kurkle/color@0.3.2': resolution: {integrity: sha512-fuscdXJ9G1qb7W8VdHi+IwRqij3lBkosAm4ydQtEmbY58OzHXqQhvlxqEkoz0yssNVn38bcpRWgA9PP+OGoisw==} + '@markdoc/markdoc@0.4.0': + resolution: {integrity: sha512-fSh4P3Y4E7oaKYc2oNzSIJVPDto7SMzAuQN1Iyx53UxzleA6QzRdNWRxmiPqtVDaDi5dELd2yICoG91csrGrAw==} + engines: {node: '>=14.7.0'} + peerDependencies: + '@types/react': '*' + react: '*' + peerDependenciesMeta: + '@types/react': + optional: true + react: + optional: true + '@mdx-js/mdx@3.1.0': resolution: {integrity: sha512-/QxEhPAvGwbQmy1Px8F899L5Uc2KZ6JtXwlCgJmjSTBedwOZkByYcBG4GceIGPXRDsmfxhHazuS+hlOShRLeDw==} @@ -669,9 +690,18 @@ packages: '@types/hast@3.0.4': resolution: {integrity: sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==} + '@types/linkify-it@5.0.0': + resolution: {integrity: sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==} + + '@types/markdown-it@12.2.3': + resolution: {integrity: sha512-GKMHFfv3458yYy+v/N8gjufHO6MSZKCOXpZc5GXIWWy8uldwfmPn98vp81gZ5f9SVw8YYBctgfJ22a2d7AOMeQ==} + '@types/mdast@4.0.4': resolution: {integrity: sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==} + '@types/mdurl@2.0.0': + resolution: {integrity: sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==} + '@types/mdx@2.0.13': resolution: {integrity: sha512-+OWZQfAYyio6YkJb3HLxDrvnx6SWWDbC0zVPfBRzUk0/nqoDyf6dNxQi3eArPe8rJ473nobTMQ/8Zk+LxJ+Yuw==} @@ -959,6 +989,19 @@ packages: dlv@1.1.3: resolution: {integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==} + dom-serializer@2.0.0: + resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==} + + domelementtype@2.3.0: + resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==} + + domhandler@5.0.3: + resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==} + engines: {node: '>= 4'} + + domutils@3.1.0: + resolution: {integrity: sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==} + dset@3.1.4: resolution: {integrity: sha512-2QF/g9/zTaPDc3BjNcVTGoBbXBgYfMTTceLaYcFJ/W9kggFUkhxD/hMEeuLKbugyef9SqAx8cpgwlIP/jinUTA==} engines: {node: '>=4'} @@ -1197,6 +1240,9 @@ packages: html-whitespace-sensitive-tag-names@3.0.1: resolution: {integrity: sha512-q+310vW8zmymYHALr1da4HyXUQ0zgiIwIicEfotYPWGN0OJVEN/58IJ3A4GBYcEq3LGAZqKb+ugvP0GNB9CEAA==} + htmlparser2@9.1.0: + resolution: {integrity: sha512-5zfg6mHUoaer/97TxnGpxmbR7zJtPwIYFMZ/H5ucTlPZhKvtum05yiPK3Mgai3a0DyVxv7qYqoweaEd2nrYQzQ==} + http-cache-semantics@4.1.1: resolution: {integrity: sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==} @@ -2216,6 +2262,22 @@ snapshots: '@astrojs/internal-helpers@0.4.1': {} + '@astrojs/markdoc@0.11.5(astro@4.16.10(rollup@4.24.4)(typescript@5.6.3))': + dependencies: + '@astrojs/internal-helpers': 0.4.1 + '@astrojs/markdown-remark': 5.3.0 + '@astrojs/prism': 3.1.0 + '@markdoc/markdoc': 0.4.0 + astro: 4.16.10(rollup@4.24.4)(typescript@5.6.3) + esbuild: 0.21.5 + github-slugger: 2.0.0 + gray-matter: 4.0.3 + htmlparser2: 9.1.0 + transitivePeerDependencies: + - '@types/react' + - react + - supports-color + '@astrojs/markdown-remark@5.3.0': dependencies: '@astrojs/prism': 3.1.0 @@ -2652,6 +2714,10 @@ snapshots: '@kurkle/color@0.3.2': {} + '@markdoc/markdoc@0.4.0': + optionalDependencies: + '@types/markdown-it': 12.2.3 + '@mdx-js/mdx@3.1.0(acorn@8.14.0)': dependencies: '@types/estree': 1.0.6 @@ -2854,10 +2920,22 @@ snapshots: dependencies: '@types/unist': 3.0.3 + '@types/linkify-it@5.0.0': + optional: true + + '@types/markdown-it@12.2.3': + dependencies: + '@types/linkify-it': 5.0.0 + '@types/mdurl': 2.0.0 + optional: true + '@types/mdast@4.0.4': dependencies: '@types/unist': 3.0.3 + '@types/mdurl@2.0.0': + optional: true + '@types/mdx@2.0.13': {} '@types/ms@0.7.34': {} @@ -3176,6 +3254,24 @@ snapshots: dlv@1.1.3: {} + dom-serializer@2.0.0: + dependencies: + domelementtype: 2.3.0 + domhandler: 5.0.3 + entities: 4.5.0 + + domelementtype@2.3.0: {} + + domhandler@5.0.3: + dependencies: + domelementtype: 2.3.0 + + domutils@3.1.0: + dependencies: + dom-serializer: 2.0.0 + domelementtype: 2.3.0 + domhandler: 5.0.3 + dset@3.1.4: {} eastasianwidth@0.2.0: {} @@ -3571,6 +3667,13 @@ snapshots: html-whitespace-sensitive-tag-names@3.0.1: {} + htmlparser2@9.1.0: + dependencies: + domelementtype: 2.3.0 + domhandler: 5.0.3 + domutils: 3.1.0 + entities: 4.5.0 + http-cache-semantics@4.1.1: {} i18next@23.16.5: diff --git a/src/content/blogs/the-search-for-the-perfect-ssh-key.md b/src/content/blogs/the-search-for-the-perfect-ssh-key.md deleted file mode 100644 index ca6ca01..0000000 --- a/src/content/blogs/the-search-for-the-perfect-ssh-key.md +++ /dev/null @@ -1,118 +0,0 @@ ---- -title: The search for the perfect SSH key -description: How you can embed your name in an SSH key -date: 2024-11-14 ---- - -SSH keys are a widely used tool among developers, -they are the equivalent of a username and password in the development world. -They allow you to prove your identity and they are the gateway -into accessing servers remotely in a secure manner. - -### The ssh public key format - -When generating an ssh key, you get 2 files, one with no extension that stores the private key -and another that ends with a `.pub`. -The public key is what you share publicly on your profile or add to a remote server to login through SSH. - -Here's how a typical SSH public key looks - -``` -ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBSSj+yfJLWEb+Df4r4603TOFAUBREYS43qQB+c9i9UW -``` - -Let's break it down - -- The first part `ssh-ed25519` is the algorithm type that was used, other common algorithms are `ssh-rsa` and `ssh-ecdsa` -- The second part is a base64-encoded binary format consiting of the following - - the length of the algorithm string, for ed25519 it's always 11 (4 bytes long) - - the algorithm type, for ed25519 it's always `ssh-ed25519` in binary (11 bytes long) - - the length of the key, 32 bytes for ed25519 (4 bytes long) - - the raw bytes for the ed25519 key (32 bytes long) - -## Embedding a word in base64 - -Base64 is a widely used format for displaying binary in a compact and human readable way, -it uses A-Z, a-z, 0-9, '/' and '+' adding up to 64 unique characters. - -It's possible to choose specific bytes in a way that when encoding it with base64 -it will form a word. - -For example, to encode "Kyren" in base64, we can use the following bytes -`00101011 00101010 01001110` or in hex `2b 2a de` - -So by controlling the 32 bytes at the end of the ssh we are able to get -a ssh public key containig any keyword we want. - -## Brute Force - -Unfortunately this won't work, we still want to be able to use the key -so we will need to know the corresponding private key, but it's impossible to reverse engineer -the private key using the public one, that's why cryptography is sosecure. - -The solution is to just generate a bunch of keys until we get lucky and find the desired keyword. -So that's exactly what I have done, here's a basic go program that does that. - -```go -package main - -import ( - "bytes" - "crypto/ed25519" - "encoding/base64" - "fmt" - - "golang.org/x/crypto/ssh" -) - -func main() { - keyword := []byte("Kyren") - for { - pubKey, privKey, _ := ed25519.GenerateKey(nil) - sshPubKey, _ := ssh.NewPublicKey(pubKey) - pub := ssh.MarshalAuthorizedKey(sshPubKey) - if bytes.Contains(pub, keyword) { - privBase64 := base64.StdEncoding.EncodeToString(privKey) - fmt.Printf("Found %s in %s with private key %s\n", string(keyword), string(pub), privBase64) - break - } - } -} -``` - -I have later improved this program by adding multithreading and made it easier to use. -The final code can be seen on my GitHub [in this link](https://github.com/Kyren223/ed25519-key-gen). - -## Results - -After running it for 2 days (about 24 hours in total) on my laptop with a AMD Ryzen 5 7530U (12 threads), -here are the results: - -``` -Completed Search -Time Elapsed: 12h9m11.225248108s -Searched: 6733606724 Found: 737 -``` - -- Generated and searched 150k SSH keys per second -- Found a 5-character keyword every 9.1 million keys or about 1 every minute -- Found a 6 character keywords every 1/64 of every 5-character keyword, or about 1 every hour -- Found 5-character that are at the end of the SSH key 1/50 of every 5-character keyword - -My goal was to find either a `/kyren` or `+kyren` at the end of the key, -on average that'd be 1/3200 5-character keywords. -At the end after only 1862 5-char keywords I found 3 keys that matched what I was looking for: - -``` -ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFjS3Pl+DZKyyoAl+ZN0FDsxyOWzLgNQo+YaYe+KYREN -ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIO7P9K9D5RkBk+JCRRS6AtHuTAc6cRpXfRfRMg/Kyren -ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKEKL6f7j8U70si1YGPBUhIcsHtJIUeH+uiUlS+kyren -``` - -I will be going with the middle one as my permanent SSH key. - -I hope this inspires you to try and find your own SSH key, -hopefully your name is not 7 characters long, -and if it's 8, I hope you have 170 years to spare. - -Thanks for reading! this is my first blog post so any feedback will be appreciated! diff --git a/src/content/blogs/the-search-for-the-perfect-ssh-key.mdx b/src/content/blogs/the-search-for-the-perfect-ssh-key.mdx new file mode 100644 index 0000000..215a411 --- /dev/null +++ b/src/content/blogs/the-search-for-the-perfect-ssh-key.mdx @@ -0,0 +1,117 @@ +--- +title: The search for the perfect SSH key +description: How you can embed your name in an SSH key +date: 2024-11-15 +--- + +SSH keys are a widely used tool among developers, +they are the equivalent of a username and password in the development world. +They allow you to prove your identity and they are the gateway +into accessing servers remotely in a secure manner. + +## The SSH public key format + +When generating an ssh key, you get 2 files, one with no extension that stores the private key +and another that ends with a `.pub`. +The public key is what you share publicly on your profile or add to a remote server to login through SSH. + +Here's how a typical SSH public key looks + +``` +ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBSSj+yfJLWEb+Df4r4603TOFAUBREYS43qQB+c9i9UW +``` + +It consists of 2 parts, the algorithm, in this case it's +`ssh-ed25519`, other common algorithms are `ssh-rsa` and `ssh-ecdsa`. +The second part is a base64 encoded custom binary format. + +Let's break it down + +- the length of the algorithm string, for ed25519 it's always 11 (4 bytes long) +- the algorithm type, for ed25519 it's always `ssh-ed25519` in binary (11 bytes long) +- the length of the key, 32 bytes for ed25519 (4 bytes long) +- the raw bytes for the ed25519 key (32 bytes long) + +## Embedding a word in base64 + +Base64 is a widely used format for displaying binary in a compact and human readable way, +it uses A-Z, a-z, 0-9, '/' and '+' adding up to 64 unique characters. + +It's possible to choose specific bytes in a way that when encoding it with base64 +it will form a word. + +For example, to encode "Kyren" in base64, we can use the bytes +`00101011 00101010 01001110` or in hex `2b 2a de`. + +So by controlling the 32 bytes at the end of the ssh we are able to get +a ssh public key containig any keyword we want. + +## Brute Force + +Unfortunately this approach won't work, we still want to be able to use the key +so we will need to know the corresponding private key, but it's impossible to reverse engineer +the private key using the public one, that's why cryptography is so secure. + +The solution is simple, just generate a bunch of keys until we get lucky and find the desired keyword. +So that's what I have done, here's a basic go program that does exactly that. + +```go +package main + +import ( + "bytes" + "crypto/ed25519" + "encoding/base64" + "fmt" + + "golang.org/x/crypto/ssh" +) + +func main() { + keyword := []byte("Kyren") + for { + pubKey, privKey, _ := ed25519.GenerateKey(nil) + sshPubKey, _ := ssh.NewPublicKey(pubKey) + pub := ssh.MarshalAuthorizedKey(sshPubKey) + if bytes.Contains(pub, keyword) { + privBase64 := base64.StdEncoding.EncodeToString(privKey) + fmt.Printf("Found %s in %s with private key %s\n", string(keyword), string(pub), privBase64) + break + } + } +} +``` + +I have later improved this program by adding multithreading and made it easier to use. +The final code is available on my GitHub [at this link](https://github.com/Kyren223/ed25519-key-gen). + +## Results + +After running it for 2 days (about 24 hours in total) on my AMD Ryzen 5 7530U laptop (12 threads), +here are the results: + +``` +Completed Search +Time Elapsed: 12h9m11.225248108s +Searched: 6733606724 Found: 737 +``` + +- Generated and searched 150k SSH keys per second +- Found a 5-character keyword every 9.1 million keys or about 1 every minute +- Found a 6 character keyword every 1/64 of every 5-character keyword, or about 1 every hour +- Found 5-character that are at the end of the SSH key 1/50 of every 5-character keyword + +My goal was to find a `/kyren` at the end of the key, +on average that'd be 1 every 3200 5-character keywords. + +At the end after only 1862 keywords I found the key, here it is + +``` +ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIO7P9K9D5RkBk+JCRRS6AtHuTAc6cRpXfRfRMg/Kyren +``` + +I hope this inspires you to try and find your own SSH key, +hopefully your name is not 7 characters long, +and if it's 8, I hope you have 170 years to spare. + +Thanks for reading! this is my first blog post so any feedback will be appreciated! diff --git a/src/pages/blogs/[...slug].astro b/src/pages/blogs/[...slug].astro index dbecb22..b8fa5b4 100644 --- a/src/pages/blogs/[...slug].astro +++ b/src/pages/blogs/[...slug].astro @@ -2,6 +2,8 @@ import { getCollection } from "astro:content"; import Terminal from "@layouts/Terminal.astro"; import BlogItem from "@components/BlogItem.astro"; +import Link from "@components/Link.astro"; +import TerminalBorder from "@components/TerminalBorder.astro"; export async function getStaticPaths() { const blogEntries = await getCollection("blogs"); @@ -16,8 +18,8 @@ const { Content } = await entry.render(); --- -
-
+
+
-

Somewhat of a long heading

- + +
+
+ + + vim ~/blogs/next-blog.md + + + vim ~/blogs/next-blog.md +
diff --git a/tailwind.config.mjs b/tailwind.config.mjs index 16b793f..94db283 100644 --- a/tailwind.config.mjs +++ b/tailwind.config.mjs @@ -4,11 +4,7 @@ export default { preflight: false, }, content: ["./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}"], - // content: ["./src/**/*.{astro,html,js,jsx,svelte,ts,tsx,vue}"], theme: { extend: {}, }, - plugins: [ - // require("@tailwindcss/typography") - ], }; -- cgit v1.3.1