All posts by Torleif

Batch convert SVG to PNG on Windows using Inkscape

Needed to convert several SVGs to PNG, and discovered the free Inkscape easily can be used in batch scripts.

The following .bat file will convert all SVGs dropped on it to a PNG with height 48 placed next to the original SVG. More options can be found in the Inkscape manual.

@echo off
for %%f in (%*) do (
    echo %%~f
    "C:\Program Files\Inkscape\inkscape.exe" ^
      -z ^
      --export-background-opacity=0 ^
      --export-height=48 ^
      --export-png="%%~dpnf.png" ^
      --file="%%~f"

)

Setting up GPG signing for Git/GitHub on Windows

What I did to get from working GPG to green and verified signatures for Git commits and tags on GitHub.

  1. Find the long id of the Signing key we want to use:
    🔶 $ gpg --edit-key alice
    gpg (GnuPG) 2.0.30; Copyright (C) 2015 Free Software Foundation, Inc.
    This is free software: you are free to change and redistribute it.
    There is NO WARRANTY, to the extent permitted by law.

    Secret key is available.

    pub  4096R/AA79CCAE  created: 2017-08-23  expires: never       usage: SC
                         trust: ultimate      validity: ultimate
    sub  4096R/62275E24  created: 2017-08-23  expires: never       usage: S 👈
    sub  4096R/4AEA9524  created: 2017-08-23  expires: never       usage: E
    [ultimate] (1). Alice Person (alice) <alice.person@example.com>
    [ultimate] (2)  Alice Person (alice) <alice@example.org>

    🔶 gpg> quit

    🔶 $ gpg --list-secret-keys --keyid-format LONG alice
    sec   4096R/8C0BBECBAA79CCAE 2017-08-23
    uid                          Alice Person (alice) <alice.person@example.com>
    uid                          Alice Person (alice) <alice@example.org>
    ssb   4096R/6ADB9D4262275E24 2017-08-23 👈
    ssb   4096R/33F2E1644AEA9524 2017-08-23

    Note: So in this case we want 6ADB9D4262275E24

  2. Configure git and (optionally) make it sign all commits by default:
    🔷 $ git config --global user.name "Alice Person"
    🔷 $ git config --global user.email "alice.person@example.com"
    🔶 $ git config --global user.signingkey "6ADB9D4262275E24"
    🔷 $ git config --global commit.gpgsign true
    🔷 $ git config --global push.gpgsign if-asked
    🔶 $ where gpg
    C:\Program Files (x86)\GNU\GnuPG\pub\gpg.exe
    🔶 $ git config --global gpg.program "C:/Program Files (x86)/GNU/GnuPG/pub/gpg.exe"

    Note: If repo specific, just skip --global and run the command in the repo instead.

Test it…

  1. Do a commit:
    🔷 $ git init gpg-test
    🔷 $ cd gpg-test
    🔷 $ touch file.txt
    🔶 $ git commit -a -m "Signed commit"

    You need a passphrase to unlock the secret key for
    user: "Alice Person (alice) <alice.person@example.com>"
    4096-bit RSA key, ID 62275E24, created 2017-08-23 (main key ID AA79CCAE)

    [master (root-commit) 2814856] Works...?
     1 file changed, 0 insertions(+), 0 deletions(-)
     create mode 100644 file.txt

    Note: One can also use the the -S option as alternative to using the commit.gpgsign true config, but as a forgetful person, I’d advice against that… Either set the config globally, or for the specific repo you need it for.

  2. Verify commit was signed:
    🔷 $ git log --show-signature
    commit 2814856365a07b3deb374f1337258102c06b77ef
    gpg: Signature made 08/23/17 06:18:50 W. Europe Daylight Time^M
    gpg:                using RSA key 6ADB9D4262275E24^M
    gpg: Good signature from "Alice Person (alice) <alice.person@example.com>" [ultimate]^M
    gpg:                 aka "Alice Person (alice) <alice@example.org>" [ultimate]^M
    Author: Alice Person <alice.person@example.com>
    Date:   Wed Aug 23 06:18:48 2017 +0200

        Signed commit
  3. Add a signed tag, using -s:
    🔶 $ git tag -s v1 -m "Signed tag"

    You need a passphrase to unlock the secret key for
    user: "Alice Person (alice) <alice.person@example.com>"
    4096-bit RSA key, ID 62275E24, created 2017-08-23 (main key ID AA79CCAE)

    Note: Unfortunately, unlike for commits, there is no tag.gpgsign true config as of writing, so to sign tags the -s option has to be remembered.

  4. Verify tag was signed:
    🔷 $ git tag -v v1
    gpg: Signature made 08/23/17 06:34:18 W. Europe Daylight Time
    gpg:                using RSA key 6ADB9D4262275E24
    gpg: Good signature from "Alice Person (alice) <alice.person@example.com>" [ultimate]
    gpg:                 aka "Alice Person (alice) <alice@example.org>" [ultimate]
    object 53e7f2e637eaf3c47b5dcad30b57be7b6829be02
    type commit
    tag v1
    tagger Alice Person <alice.person@example.com> 1503462856 +0200

    Signed tag

Add GPG key to GitHub

  1. Export the public key:
    🔶 $ gpg -a --export alice > public.txt
  2. Copy it.
  3. Go to GPG keys on GitHub.
  4. New GPG Key.
  5. Paste it.
  6. Add GPG Key.
  7. Pushed commits and tags should now look verified, as in this post: GPG signature verification

Sources: help.github.com, StackOverflow, git-scm.com

Setting up GPG on Windows

What I did to get from zero to a good working (hopefully) secure GPG key set, usable for signing and encrypting stuff on Windows…

  1. Install Gpg4win.
  2. Create main/root key:
    🔶 $ gpg --gen-key
    gpg (GnuPG) 2.0.30; Copyright (C) 2015 Free Software Foundation, Inc.
    This is free software: you are free to change and redistribute it.
    There is NO WARRANTY, to the extent permitted by law.

    Please select what kind of key you want:
       (1) RSA and RSA (default)
       (2) DSA and Elgamal
       (3) DSA (sign only)
       (4) RSA (sign only)
    🔶 Your selection? 4
    RSA keys may be between 1024 and 4096 bits long.
    What keysize do you want? (2048) 4096
    Requested keysize is 4096 bits
    Please specify how long the key should be valid.
             0 = key does not expire
          <n>  = key expires in n days
          <n>w = key expires in n weeks
          <n>m = key expires in n months
          <n>y = key expires in n years
    🔶 Key is valid for? (0) 0
    Key does not expire at all
    🔶 Is this correct? (y/N) y

    GnuPG needs to construct a user ID to identify your key.

    🔶 Real name: Alice Person
    🔶 Email address: alice.person@example.com
    🔶 Comment: alice
    You selected this USER-ID:
        "Alice Person (alice) <alice.person@example.com>"

    🔶 Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? o
    You need a Passphrase to protect your secret key.

    We need to generate a lot of random bytes. It is a good idea to perform
    some other action (type on the keyboard, move the mouse, utilize the
    disks) during the prime generation; this gives the random number
    generator a better chance to gain enough entropy.
    gpg: key AA79CCAE marked as ultimately trusted
    public and secret key created and signed.

    gpg: checking the trustdb
    gpg: public key of ultimately trusted key AA77EE54 not found
    gpg: 3 marginal(s) needed, 1 complete(s) needed, PGP trust model
    gpg: depth: 0  valid:   2  signed:   0  trust: 0-, 0q, 0n, 0m, 0f, 2u
    pub   4096R/AA79CCAE 2017-08-23
          Key fingerprint = 98A1 5DD0 0653 55BB 3358  B35C 8C0B BECB AA79 CCAE
    uid       [ultimate] Alice Person (alice) <alice.person@example.com>

    Note that this key cannot be used for encryption.  You may want to use
    the command "--edit-key" to generate a subkey for this purpose.
  3. Open the key for editing:
    🔶 $ gpg --edit-key alice
    gpg (GnuPG) 2.0.30; Copyright (C) 2015 Free Software Foundation, Inc.
    This is free software: you are free to change and redistribute it.
    There is NO WARRANTY, to the extent permitted by law.

    Secret key is available.

    pub  4096R/AA79CCAE  created: 2017-08-23  expires: never       usage: SC
                         trust: ultimate      validity: ultimate
    [ultimate] (1). Alice Person (alice) <alice.person@example.com>
  4. (Optionally) Add other user ids, and set the right one as primary:
    🔷 gpg> adduid
    🔷 Real name: Alice Person
    🔷 Email address: alice@example.org
    🔷 Comment: alice
    You selected this USER-ID:
        "Alice Person (alice) <alice@example.org>"

    🔷 Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? o

    You need a passphrase to unlock the secret key for
    user: "Alice Person (alice) <alice.person@example.com>"
    4096-bit RSA key, ID AA79CCAE, created 2017-08-23


    pub  4096R/AA79CCAE  created: 2017-08-23  expires: never       usage: SC
                         trust: ultimate      validity: ultimate
    [ultimate] (1)  Alice Person (alice) <alice.person@example.com>
    [ unknown] (2). Alice Person (alice) <alice@example.org>

    # Select one of them
    🔷 gpg> uid 1

    pub  4096R/AA79CCAE  created: 2017-08-23  expires: never       usage: SC
                         trust: ultimate      validity: ultimate
    [ultimate] (1)* Alice Person (alice) <alice.person@example.com>
    [ unknown] (2). Alice Person (alice) <alice@example.org>

    🔷 gpg> primary

    You need a passphrase to unlock the secret key for
    user: "Alice Person (alice) <alice.person@example.com>"
    4096-bit RSA key, ID AA79CCAE, created 2017-08-23


    pub  4096R/AA79CCAE  created: 2017-08-23  expires: never       usage: SC
                         trust: ultimate      validity: ultimate
    [ultimate] (1)* Alice Person (alice) <alice.person@example.com>
    [ unknown] (2)  Alice Person (alice) <alice@example.org>
  5. Add subkeys for signing and encryption:
    🔶 gpg> addkey
    Key is protected.

    You need a passphrase to unlock the secret key for
    user: "Alice Person (alice) <alice.person@example.com>"
    4096-bit RSA key, ID AA79CCAE, created 2017-08-23

    Please select what kind of key you want:
       (3) DSA (sign only)
       (4) RSA (sign only)
       (5) Elgamal (encrypt only)
       (6) RSA (encrypt only)
    🔶 Your selection? 4
    RSA keys may be between 1024 and 4096 bits long.
    🔶 What keysize do you want? (2048) 4096
    Requested keysize is 4096 bits
    Please specify how long the key should be valid.
             0 = key does not expire
          <n>  = key expires in n days
          <n>w = key expires in n weeks
          <n>m = key expires in n months
          <n>y = key expires in n years
    🔶 Key is valid for? (0) 0
    Key does not expire at all
    🔶 Is this correct? (y/N) y
    🔶 Really create? (y/N) y
    We need to generate a lot of random bytes. It is a good idea to perform
    some other action (type on the keyboard, move the mouse, utilize the
    disks) during the prime generation; this gives the random number
    generator a better chance to gain enough entropy.

    pub  4096R/AA79CCAE  created: 2017-08-23  expires: never       usage: SC
                         trust: ultimate      validity: ultimate
    sub  4096R/62275E24  created: 2017-08-23  expires: never       usage: S
    [ultimate] (1)* Alice Person (alice) <alice.person@example.com>
    [ unknown] (2)  Alice Person (alice) <alice@example.org>

    🔶 gpg> addkey
    Key is protected.

    You need a passphrase to unlock the secret key for
    user: "Alice Person (alice) <alice.person@example.com>"
    4096-bit RSA key, ID AA79CCAE, created 2017-08-23

    Please select what kind of key you want:
       (3) DSA (sign only)
       (4) RSA (sign only)
       (5) Elgamal (encrypt only)
       (6) RSA (encrypt only)
    🔶 Your selection? 6
    RSA keys may be between 1024 and 4096 bits long.
    🔶 What keysize do you want? (2048) 4096
    Requested keysize is 4096 bits
    Please specify how long the key should be valid.
             0 = key does not expire
          <n>  = key expires in n days
          <n>w = key expires in n weeks
          <n>m = key expires in n months
          <n>y = key expires in n years
    🔶 Key is valid for? (0) 0
    Key does not expire at all
    🔶 Is this correct? (y/N) y
    🔶 Really create? (y/N) y
    We need to generate a lot of random bytes. It is a good idea to perform
    some other action (type on the keyboard, move the mouse, utilize the
    disks) during the prime generation; this gives the random number
    generator a better chance to gain enough entropy.

    pub  4096R/AA79CCAE  created: 2017-08-23  expires: never       usage: SC
                         trust: ultimate      validity: ultimate
    sub  4096R/62275E24  created: 2017-08-23  expires: never       usage: S
    sub  4096R/4AEA9524  created: 2017-08-23  expires: never       usage: E
    [ultimate] (1)* Alice Person (alice) <alice.person@example.com>
    [ unknown] (2)  Alice Person (alice) <alice@example.org>
  6. Save (and quit):
    🔶 gpg> save
  7. Export keys for (safe!) storage:
    🔶 $ set id=AA79CCAE
    🔶 $ gpg -a --export %id% > %id%_public.asc
    🔶 $ gpg -a --export-secret-keys %id% > %id%_private.asc
    🔶 $ gpg -a --export-secret-subkeys %id% > %id%_subkeys.asc
  8. Export revocation file:
    🔶 $ gpg -a --gen-revoke %id% > %id%_revoke_cert.asc

    sec  4096R/AA79CCAE 2017-08-23 Alice Person (alice) <alice.person@example.com>

    Create a revocation certificate for this key? (y/N) y
    Please select the reason for the revocation:
      0 = No reason specified
      1 = Key has been compromised
      2 = Key is superseded
      3 = Key is no longer used
      Q = Cancel
    (Probably you want to select 1 here)
    🔶 Your decision? 1
    Enter an optional description; end it with an empty line:
    🔶 >
    Reason for revocation: Key has been compromised
    (No description given)
    🔶 Is this okay? (y/N) y

    You need a passphrase to unlock the secret key for
    user: "Alice Person (alice) <alice.person@example.com>"
    4096-bit RSA key, ID AA79CCAE, created 2017-08-23

    Revocation certificate created.

    Please move it to a medium which you can hide away; if Mallory gets
    access to this certificate he can use it to make your key unusable.
    It is smart to print this certificate and store it away, just in case
    your media become unreadable.  But have some caution:  The print system of
    your machine might store the data and make it available to others!

Source(s): blog.bravi.org

PHP: Unset all defined variables

foreach(get_defined_vars() as $k => $v)
    unset($$k);
unset($k, $v);

For example handy in this setting:

foreach($iterable as $item)
{
    extract($item);
    unset($item);

    // Define another variable, for only some of the items
    if($foo == 'bar')
        $x = 2;

    // Yield all defined vars
    yield get_defined_vars();

    // Cleanup, to prevent $x and other variables from
    // sticking around to the next iteration
    foreach(get_defined_vars() as $k => $v)
        unset($$k);
    unset($k, $v);
}

PHP: Pathable RecursiveIteratorIterator

Needed to recursively loop through a multi-dimensional array and print out each leaf-node with its full “path”.

For this I used an RecursiveArrayIterator for the array and a RecursiveIteratorIterator for the recursion. Thought I was home free because I had used a method called getSubpathname before, but turned out that was just something the RecursiveDirectoryIterator had…

So, had to grow my own… noting it here for others and the future:

class PathableRecursiveIteratorIterator
    extends RecursiveIteratorIterator
{
    /**
     * Gets the path to current node, i.e. each
     *   key "upwards", including self.
     *
     * @param null|string $glue Optional $glue for implode().
     *
     * @return array|string The keys, from root to self,
     *   as an array; or as a string if $glue is provided.
     */

    public function getPath($glue = null)
    {
        for($i = 0; $i < $this->getDepth(); $i++)
            $path[] = $this->getSubIterator($i)->key();

        $path[] = $this->key();

        return $glue !== null
            ? implode($glue, $path)
            : $path;
    }
}

Based upon: StackOverflow