The plural of "regex" is "production bugs"
Well, even though the statement is quite provocative, I think there's some truth to it.
Regex is powerful, but it also quickly becomes a footgun. Over- and under-matching happens to everyone who works with it, no matter how long or well they know Regex.
In my opinion, ad-hoc tasks are the most suitable use case. The more an expression becomes part of a larger program logic and probably also takes on more complex structures (e.g., validate an email address for me), the more potentially problematic its use becomes.
For more complex structures, there are other tools, such as a proper parser.
I still have on my list to learn how to build parsers, both out of interest and necessity.
Regex is fundamentally very simple and easy to learn; it just looks like a salad. However, I'm not sure who (as in target audience) should really master Regex.
In production code, Regex should actually almost never be used, as the risk of having overlooked something is often too high. And for things like form validation, there should (or maybe already are) openly standardized expressions (email, DNS name, etc.).
Using Regex to break down / validate addresses, names, or other less clearly definable structures is only obvious to those who have invested enough time and energy in learning Regex. But I think that few people do that.
In this regard, my opinion on Regex is similar to that of C or ASM: Very powerful, great that it exists, very much worth learning, high footgun potential, don't use it in critical prod environments unless you have good knowledge about it and reason to do so.
This is a comment to a video I've seen: YouTube: NetworkChuck - the most SECURE browser!! (testing it with malware)
This is just as problematic as any of the usual commercial VPN providers. It's not solving any bigger problems. This is not a long-term solution for everyone. The biggest part of many effective solutions is education and giving people the ability to understand the enviroment & problemdomain, not another tool / service / company or gov one has to (en)trust.
Here is a solution to a bigger problem, that is related to this: Building a new desktop & server OS from the ground up, by analyzing the issues and solutions / workarounds we encountered in the past ~30 years and using that to design something that accounts for all these things from the beginning. Repeat that every couple of decades or so.
The current state of operations is doing imense patchwork on architecture design from decades ago, which is an eternity in the context of the current rate of technological development.
A SSL keypair is a combination of a private key and a public key used for secure communication. The private key is kept secret by the owner and the public key is shared with others. A certificate is a digital document that contains information about the owner of a public key, including the domain name, public key, and signature of the issuer. The certificate is used to secure communication between a client and a server by establishing trust in the identity of the certificate owner.
In short, a certificate is a digital identity card that is verified by a trusted third party and used to secure communication. This verification process involves creating an SSL certificate chain, which consists of the following components:
We will explain each of these components in detail, along with the process of revoking a leaf certificate and a brief history of certificate revocation.
Here is an example of the contents of an OpenSSL configuration file (openssl.cnf) that can be used for this guide.
This configuration file sets up a basic certificate authority, with a root CA certificate and an intermediate CA certificate. It sets the default policy to match the country name, state or province name, organization name, and common name of the certificate. The basic constraints section specifies that the leaf certificate should not be used as a certificate authority, and the subject key identifier and authority key identifier extensions are used to link the certificate to its corresponding private key and the issuing CA certificate.
cat << 'EOF' >openssl.cnf [ ca ] default_ca = CA_default [ CA_default ] dir = . certs = $dir new_certs_dir = $dir/newcerts database = $dir/index serial = $dir/serial crlnumber = $dir/crlnumber crl_dir = $dir/crl crl = $dir/intermediateCA.crl crl_extensions = crl_ext unique_subject = no certificate = $dir/intermediateCA.pem private_key = $dir/intermediateCA.key x509_extensions = usr_cert default_crl_days = 7 default_days = 365 default_md = sha256 policy = policy_match [ policy_match ] commonName = supplied countryName = optional stateOrProvinceName = optional organizationName = optional organizationalUnitName = optional emailAddress = optional [ req ] default_bits = 4096 distinguished_name = req_distinguished_name x509_extensions = v3_ca string_mask = utf8only req_extensions = v3_req [ req_distinguished_name ] commonName = Common Name (e.g. server FQDN or YOUR name) commonName_max = 64 commonName_default = [ v3_ca ] subjectKeyIdentifier = hash basicConstraints = CA:true authorityKeyIdentifier = keyid:always,issuer:always keyUsage = cRLSign, keyCertSign [ v3_req ] basicConstraints = CA:false keyUsage = nonRepudiation, digitalSignature, keyEncipherment [ usr_cert ] subjectKeyIdentifier = hash basicConstraints = CA:false authorityKeyIdentifier = keyid:always,issuer:always [ crl_ext ] authorityKeyIdentifier=keyid:always EOF
And with the following set of commands we are creating the self-signed root CA.
# create required file structure mkdir -p newcerts touch index crlnumber echo 01 >serial echo 1000 >crlnumber # generate root ca private key openssl genrsa -out rootCA.key 4096 # self-sign openssl req -config openssl.cnf -new -x509 -days 18250 -subj "/CN=Test Root CA" -key rootCA.key -out rootCA.pem
# generate intermediate ca private key openssl genrsa -out intermediateCA.key 4096 # create signing request for the root ca openssl req -config openssl.cnf -new -subj "/CN=Test Sub CA" -key intermediateCA.key -out intermediateCA.csr # sign the request, using the root ca openssl ca -config openssl.cnf -batch -extensions v3_ca -days 1825 -in intermediateCA.csr -out intermediateCA.pem -keyfile rootCA.key -cert rootCA.pem
# generate leaf certificate private key openssl genrsa -out leaf.key 4096 # create signing request for intermediate ca openssl req -config openssl.cnf -new -subj "/CN=Test Server" -key leaf.key -out leaf.csr # sign the request, using the intermediate ca openssl ca -config openssl.cnf -batch -in leaf.csr -out leaf.pem
If a leaf certificate is compromised, it must be revoked. The process of revoking a certificate involves the root CA adding the certificate to a Certificate Revocation List (CRL) or publishing the revocation information in an Online Certificate Status Protocol (OCSP) response.
# revoke the leaf certificate openssl ca -config openssl.cnf -revoke leaf.pem # update the crl of the intermediate ca (the issuer) openssl ca -config openssl.cnf -gencrl -out intermediateCA.crl
In the early days of SSL certificates, CRLs were used as the primary method for revoking certificates. However, CRLs had several limitations, such as the large size of the lists, the difficulty in updating them, and the delay in propagating updates to clients. As a result, OCSP was developed as a more efficient way to check the revocation status of certificates. Today, both CRLs and OCSP are used to verify the revocation status of certificates.
The SSL certificate chain involves several parties, including the root CA, the intermediate CA, the leaf certificate owner, and the client that is connecting to the server.
The SSL certificate chain is a complex system that involves several parties and fundamentally relies on trust. While the trust model, as it's implemented today, has some issues, it remains an essential component of secure communication on the internet. By understanding how the certificate chain works, you can take steps to protect your online assets and improve the security of your systems.
Today I did a little pointer exercise using Rust.
This is what we are going to do:
1. Allocate a new instance of `Point` struct on the heap
use std::ptr; struct Point { x: u8, y: u8, z: u8, } fn main() { let mut point = Box::new(Point { x: 0, y: 0, z: 0 }); }
2. Change values of Point instance inside `Box<T>`
point.x = u8::max_value(); // 0 point.y = u8::min_value(); // 255 point.z = u8::max_value(); // 0
3. Inspect the memory addr of the `Box<T>` and the values of primitive types by using existing scope reference of the current stack (safe)
// get raw memory address of `Box<Point>`: // &point: get reference to `point` // as *const Box<Point>: cast reference into raw pointer of type T // as usize: cast raw pointer of type T into usize let mem_addr_of_box = &point as *const Box<Point> as usize; // get raw memory address of `Point`: // &*point: get reference to `Point` by dereferenceing instance of `Box<Point>` first // as *const Point: cast reference into raw pointer of type T // as usize: cast raw pointer of type T into usize let mem_addr_of_point_inside_box = &*point as *const Point as usize; let x = point.x; let y = point.y; let z = point.z;
4. Inspect the memory addr of the `Box<T>` and the values of primitive types by reading from raw memory by address as u32 (unsafe)
// get raw memory address of `Box<Point>` from the current scope. let addr = &point as *const Box<Point>; // cast raw pointer of type T into usize let mem_addr_of_box = addr as usize; // perform unsafe raw memory read of `Box<Point>` resulting in raw pointer to `Point`. // as *const usize: casing into usize because addr is a memory address let mem_addr_of_point = unsafe { ptr::read(addr as *const usize) }; // perform unsafe raw memory read of `Point` as type `u32`: // read(...) as *const u32: read `Point` as u32 to inspect binary value & layout // u32 is sufficient as 3x u8 fit inside a u32 let point_value = unsafe { ptr::read_unaligned(ptr::read(addr as *const usize) as *const u32) };
5. Read point as `Point` from memory by raw pointer address into stack variable (unsafe) (values are copied)
// perform unsafe raw memory read of `Box<Point>` -> `Point` as type `Point`. let point = unsafe { ptr::read(ptr::read(addr as *const usize) as *const Point) }; // get raw memory address of `Point`: // as *const Point: cast reference into raw pointer of type T // as usize: cast raw pointer of type T into usize let mem_addr_of_point = &point as *const Point as usize; let x = point.x; let y = point.y; let z = point.z;
And here is an example of how that could look like in action Code Snippet Rust Playground via godbolt.org
I tools i love, today "date":
date --rfc-email --date="aug 15 10am" # Mon, 15 Aug 2022 10:00:00 +0200 date --rfc-email --date="+2 weeks" # Fri, 12 Aug 2022 16:17:48 +0200 date --rfc-email --date="next monday 1600" # Mon, 01 Aug 2022 16:00:00 +0200 # convert the current day of the month + one month at 9pm local time to est TZ="EST" date --rfc-email --date="next month 2100 Z+0200" # Mon, 29 Aug 2022 14:00:00 -0500
I use this almost daily 😄
Some quite some time ago i wrote about DNSSEC Quick Zone Setup with BIND.
While it worked, i didn't had it active for long. Mainly because all the manual work in keeping the signatures up-to-date.
At the time i either didn't knew about BIND9's "inline-signing yes;" and "auto-dnssec maintain;" or they didn't exist back then^^
And ow was the time i revisit the topic and "try again" on finding a better solution. And well, i think i did \o/
So far i've configured DNSSEC for one of my domains and will see how this approach is keeping up in the following months. I'll plan on writing more about DNSSEC and how my new setup works.
Until then i have a WIP document with some notes i've took along the way.
PS: I totally fell in love with Asciidoc / Asciidoctor. Maybe it's also time to re-write my blogging software, too.