GIMP – disegnare un’ellisse

Molto basic, ma uso poco Gimp e me le lo dimentico sempre:

Con lo strumento di selezione, selezionare l’area che si vuole (ad esempio un’ellisse).

Poi si può fare in due modi:

  1. Trasformare il bordo della selezione in linea: Menu Modifica > Delinea Selezione (verrà usato il colore di foreground già impostato; si può modificare lo spessore della linea dall’interno del dialog)
  2. Trasformare una selezione in tracciato: Strumenti > Tracciati (a questo punto può fare tracciato complicato quanto si vuole). Poi cliccare su Menu Modifica > Delinea Tracciato.

Risorse esterne

Manuale GIMP

Perché il cielo è blu? Feynman spiega lo scattering di Rayleigh

Blue Sky
Blue Sky

Il colore del cielo sereno in pieno giorno sufficentemente lontano dal disco solare è azzurro.

Questo colore è dovuto al fenomeno dello scattering (diffusione) di Rayleigh, cioè della radiazione emessa dalle molecole che compongono l’aria in seguito ad eccitazione della luce solare.

Dallo studio risulta che vengono diffuse tutte le frequenze ma le onde elettromagnetiche di frequenza più elevata (verso il blu) vengono diffuse molto di più, dando la dominante di azzurro.

Il link alla lezione contenuta nelle Feynman Lectures on Physics.

Non so voi, ma questa cosa mi meraviglia ogni volta.

Protetto: PKCS#11

Il contenuto è protetto da password. Per visualizzarlo inserisci di seguito la password:

Firma digitale di file PDF con iText

Questo esercizio è tratto da

Capitolo 1 – Utilizzo delle funzioni di crittografia

La prima classe da scrivere calcola firme di file.

In inglese la firma elettronica si chiama anche digest, come Reader’s Digest, la rivista americana di estrema destra che significa “Il digesto del Lettore” o, meglio, “Il riassunto del Lettore”. DeWitt Wallace, il fondatore, voleva fare una rivista che pubblicasse riassunti di articoli di altre riviste.

Digest quindi come riassunto, sintesi: è una funzione di hash crittografico che mappa messaggi lunghi in messaggi corti a lunghezza fissa facendo in modo da evitare collisioni (la probabilità che due file diversi generino lo stesso digest è molto piccola) e in modo tale da rendere impossibile (sarebbe più onesto dire “molto difficile”) risalire al contenuto di un file dalla sua firma.

I package che vedremo supportano diversi tipi di digest.

Calcolo della firma di una stringa

Realizziamo questa cosa con la classe java C1_01_DigestDefault:

package com.itextpdf.samples.signatures.chapter01;

import java.io.File;
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.security.GeneralSecurityException;
import java.security.MessageDigest;
import java.util.Arrays;

public class C1_01_DigestDefault {
    public static final String DEST = "./target/test/resources/signatures/chapter01/";

    public static final String EXPECTED_OUTPUT = "Digest using MD5: 16\n" +
            "Digest: 5f4dcc3b5aa765d61d8327deb882cf99\n" +
            "Is the password 'password'? true\n" +
            "Is the password 'secret'? false\n" +
            "Digest using SHA-1: 20\n" +
            "Digest: 5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8\n" +
            "Is the password 'password'? true\n" +
            "Is the password 'secret'? false\n" +
            "Digest using SHA-224: 28\n" +
            "Digest: d63dc919e201d7bc4c825630d2cf25fdc93d4b2f0d46706d29038d01\n" +
            "Is the password 'password'? true\n" +
            "Is the password 'secret'? false\n" +
            "Digest using SHA-256: 32\n" +
            "Digest: 5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8\n" +
            "Is the password 'password'? true\n" +
            "Is the password 'secret'? false\n" +
            "Digest using SHA-384: 48\n" +
            "Digest: a8b64babd0aca91a59bdbb7761b421d4f2bb38280d3a75ba0f21f2bebc4558" +
            "3d446c598660c94ce680c47d19c30783a7\n" +
            "Is the password 'password'? true\n" +
            "Is the password 'secret'? false\n" +
            "Digest using SHA-512: 64\n" +
            "Digest: b109f3bbbc244eb82441917ed06d618b9008dd09b3befd1b5e07394c706a8bb980b" +
            "1d7785e5976ec049b46df5f1326af5a2ea6d103fd07c95385ffab0cacbc86\n" +
            "Is the password 'password'? true\n" +
            "Is the password 'secret'? false\n" +
            "RIPEMD128 MessageDigest not available\n" +
            "RIPEMD160 MessageDigest not available\n" +
            "RIPEMD256 MessageDigest not available\n";

    protected byte[] digest;
    protected MessageDigest messageDigest;

    protected C1_01_DigestDefault(String password, String algorithm, String provider) throws GeneralSecurityException,
            UnsupportedEncodingException {
        if (provider == null) {
            messageDigest = MessageDigest.getInstance(algorithm);
        } else {
            messageDigest = MessageDigest.getInstance(algorithm, provider);
        }
        digest = messageDigest.digest(password.getBytes("UTF-8"));
    }

    public static C1_01_DigestDefault getInstance(String password, String algorithm) throws GeneralSecurityException,
            UnsupportedEncodingException {
        return new C1_01_DigestDefault(password, algorithm, null);
    }

    public static void main(String[] args) {
        File file = new File(DEST);
        file.mkdirs();

        testAll();
    }

    public static void testAll() {
        showTest("MD5");
        showTest("SHA-1");
        showTest("SHA-224");
        showTest("SHA-256");
        showTest("SHA-384");
        showTest("SHA-512");
        showTest("RIPEMD128");
        showTest("RIPEMD160");
        showTest("RIPEMD256");
    }

    public static void showTest(String algorithm) {
        try {
            C1_01_DigestDefault app = getInstance("password", algorithm);
            System.out.println("Digest using " + algorithm + ": " + app.getDigestSize());
            System.out.println("Digest: " + app.getDigestAsHexString());
            System.out.println("Is the password 'password'? " + app.checkPassword("password"));
            System.out.println("Is the password 'secret'? " + app.checkPassword("secret"));
        } catch (Exception exc) {
            System.out.println(exc.getMessage());
        }
    }

    public int getDigestSize() {
        return digest.length;
    }

    public String getDigestAsHexString() {
        return new BigInteger(1, digest).toString(16);
    }

    /* This method checks if the digest of the password is equal
     * to the digest of the text line which is passed as argument
     */
    public boolean checkPassword(String password) {
        return Arrays.equals(digest, messageDigest.digest(password.getBytes()));
    }
}

L’output del meodo main() di questa classe è il seguente

 Digest using MD5: 16
 Digest: 5f4dcc3b5aa765d61d8327deb882cf99
 Is the password 'password'? true
 Is the password 'secret'? false
 Digest using SHA-1: 20
 Digest: 5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8
 Is the password 'password'? true
 Is the password 'secret'? false
 Digest using SHA-224: 28
 Digest: d63dc919e201d7bc4c825630d2cf25fdc93d4b2f0d46706d29038d01
 Is the password 'password'? true
 Is the password 'secret'? false
 Digest using SHA-256: 32
 Digest: 5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8
 Is the password 'password'? true
 Is the password 'secret'? false
 Digest using SHA-384: 48
 Digest: a8b64babd0aca91a59bdbb7761b421d4f2bb38280d3a75ba0f21f2bebc45583d446c598660c94ce680c47d19c30783a7
 Is the password 'password'? true
 Is the password 'secret'? false
 Digest using SHA-512: 64
 Digest: b109f3bbbc244eb82441917ed06d618b9008dd09b3befd1b5e07394c706a8bb980b1d7785e5976ec049b46df5f1326af5a2ea6d103fd07c95385ffab0cacbc86
 Is the password 'password'? true
 Is the password 'secret'? false
 RIPEMD128 MessageDigest not available
 RIPEMD160 MessageDigest not available
 RIPEMD256 MessageDigest not available
 Process finished with exit code 0

Stesso calcolo ma utilizzando la libreria di crittografia Bouncy Castle

Per poter utilizzare questa libreria occorre cercare nel JAR finder questo package: bcprov-jdk15on-169.jar

Io, utilizzando come jvm quella disponbile nel JDK1.8 (/usr/lib/jvm/jdk1.8.0_111/), sistemo gli script delle librerie sotto

/usr/lib/jvm/jdk1.8.0_111/jre/lib/ext

una volta sistemato lì, l’IDE sarà in grado di trovarlo, una volta che si è specificata la directory nella configurazione (Ctrl+Alt+Maius+S – Tab “Dependencies”, aggiunta nuova dependency (plsante +) – oppure Alt+Ins).

La libreria Bouncy Castle (“A lightweight cryptography API for Java and C#”) fornisce delle API generali per la crittografia.

package com.itextpdf.samples.signatures.chapter01;

import java.io.File;
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.security.GeneralSecurityException;
import java.security.MessageDigest;
import java.security.Provider;
import java.util.Arrays;

import org.bouncycastle.jce.provider.BouncyCastleProvider;

public class C1_02_DigestBC {
    public static final String DEST = "./target/test/resources/signatures/chapter01/";

    public static final BouncyCastleProvider PROVIDER = new BouncyCastleProvider();

    public static final String EXPECTED_OUTPUT = "Digest using MD5: 16\n" +
            "Digest: 5f4dcc3b5aa765d61d8327deb882cf99\n" +
            "Is the password 'password'? true\n" +
            "Is the password 'secret'? false\n" +
            "Digest using SHA-1: 20\n" +
            "Digest: 5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8\n" +
            "Is the password 'password'? true\n" +
            "Is the password 'secret'? false\n" +
            "Digest using SHA-224: 28\n" +
            "Digest: d63dc919e201d7bc4c825630d2cf25fdc93d4b2f0d46706d29038d01\n" +
            "Is the password 'password'? true\n" +
            "Is the password 'secret'? false\n" +
            "Digest using SHA-256: 32\n" +
            "Digest: 5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8\n" +
            "Is the password 'password'? true\n" +
            "Is the password 'secret'? false\n" +
            "Digest using SHA-384: 48\n" +
            "Digest: a8b64babd0aca91a59bdbb7761b421d4f2bb38280d3a75ba0f21f2bebc45583d446c" +
            "598660c94ce680c47d19c30783a7\n" +
            "Is the password 'password'? true\n" +
            "Is the password 'secret'? false\n" +
            "Digest using SHA-512: 64\n" +
            "Digest: b109f3bbbc244eb82441917ed06d618b9008dd09b3befd1b5e07394c706a8bb980b1d7" +
            "785e5976ec049b46df5f1326af5a2ea6d103fd07c95385ffab0cacbc86\n" +
            "Is the password 'password'? true\n" +
            "Is the password 'secret'? false\n" +
            "Digest using RIPEMD128: 16\n" +
            "Digest: c9c6d316d6dc4d952a789fd4b8858ed7\n" +
            "Is the password 'password'? true\n" +
            "Is the password 'secret'? false\n" +
            "Digest using RIPEMD160: 20\n" +
            "Digest: 2c08e8f5884750a7b99f6f2f342fc638db25ff31\n" +
            "Is the password 'password'? true\n" +
            "Is the password 'secret'? false\n" +
            "Digest using RIPEMD256: 32\n" +
            "Digest: f94cf96c79103c3ccad10d308c02a1db73b986e2c48962e96ecd305e0b80ef1b\n" +
            "Is the password 'password'? true\n" +
            "Is the password 'secret'? false\n";

    protected byte[] digest;
    protected MessageDigest messageDigest;

    protected C1_02_DigestBC(String password, String algorithm, Provider provider) throws GeneralSecurityException,
            UnsupportedEncodingException {
        if (provider == null) {
            messageDigest = MessageDigest.getInstance(algorithm);
        } else {

            // BouncyCastle provider can be initialized in another way
            // by using Security.addProvider(Provider provider) method
            messageDigest = MessageDigest.getInstance(algorithm, provider);
        }
        digest = messageDigest.digest(password.getBytes("UTF-8"));
    }

    public static C1_02_DigestBC getInstance(String password, String algorithm) throws GeneralSecurityException,
            UnsupportedEncodingException {
        return new C1_02_DigestBC(password, algorithm, PROVIDER);
    }

    public static void main(String[] args) throws Exception {
        File file = new File(DEST);
        file.mkdirs();

        testAll();
    }

    public static void testAll() throws Exception {
        showTest("MD5");
        showTest("SHA-1");
        showTest("SHA-224");
        showTest("SHA-256");
        showTest("SHA-384");
        showTest("SHA-512");
        showTest("RIPEMD128");
        showTest("RIPEMD160");
        showTest("RIPEMD256");

    }

    public static void showTest(String algorithm) throws Exception {
        C1_02_DigestBC app = getInstance("password", algorithm);
        System.out.println("Digest using " + algorithm + ": " + app.getDigestSize());
        System.out.println("Digest: " + app.getDigestAsHexString());
        System.out.println("Is the password 'password'? " + app.checkPassword("password"));
        System.out.println("Is the password 'secret'? " + app.checkPassword("secret"));
    }

    public int getDigestSize() {
        return digest.length;
    }

    public String getDigestAsHexString() {
        return new BigInteger(1, digest).toString(16);
    }

    /* This method checks if the digest of the password is equal
     * to the digest of the text line which is passed as argument
     */
    public boolean checkPassword(String password) {
        return Arrays.equals(digest, messageDigest.digest(password.getBytes()));
    }
}

A differenza del default, qui al costruttore passiamo anche l’oggetto BouncyCastleProvider istanza della classe omonima, e lo passiamo esplicitamente al metodo che crea l’oggetto Digest (MessageDigest).

Anche stavolta l’output è quello atteso

Digest using MD5: 16
 Digest: 5f4dcc3b5aa765d61d8327deb882cf99
 Is the password 'password'? true
 Is the password 'secret'? false
 Digest using SHA-1: 20
 Digest: 5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8
 Is the password 'password'? true
 Is the password 'secret'? false
 Digest using SHA-224: 28
 Digest: d63dc919e201d7bc4c825630d2cf25fdc93d4b2f0d46706d29038d01
 Is the password 'password'? true
 Is the password 'secret'? false
 Digest using SHA-256: 32
 Digest: 5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8
 Is the password 'password'? true
 Is the password 'secret'? false
 Digest using SHA-384: 48
 Digest: a8b64babd0aca91a59bdbb7761b421d4f2bb38280d3a75ba0f21f2bebc45583d446c598660c94ce680c47d19c30783a7
 Is the password 'password'? true
 Is the password 'secret'? false
 Digest using SHA-512: 64
 Digest: b109f3bbbc244eb82441917ed06d618b9008dd09b3befd1b5e07394c706a8bb980b1d7785e5976ec049b46df5f1326af5a2ea6d103fd07c95385ffab0cacbc86
 Is the password 'password'? true
 Is the password 'secret'? false
 Digest using RIPEMD128: 16
 Digest: c9c6d316d6dc4d952a789fd4b8858ed7
 Is the password 'password'? true
 Is the password 'secret'? false
 Digest using RIPEMD160: 20
 Digest: 2c08e8f5884750a7b99f6f2f342fc638db25ff31
 Is the password 'password'? true
 Is the password 'secret'? false
 Digest using RIPEMD256: 32
 Digest: f94cf96c79103c3ccad10d308c02a1db73b986e2c48962e96ecd305e0b80ef1b
 Is the password 'password'? true
 Is the password 'secret'? false
 Process finished with exit code 0

Classe di encryption/decription

package com.itextpdf.samples.signatures.chapter01;

import javax.crypto.Cipher;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.security.GeneralSecurityException;
import java.security.Key;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.cert.X509Certificate;

public class C1_03_EncryptDecrypt {
    public static final String DEST = "./target/test/resources/signatures/chapter01/";

    protected static final String KEYSTORE = "./src/test/resources/encryption/ks";

    protected static final String PASSWORD = "password";
    protected KeyStore ks;

    public static void main(String[] args) throws Exception {
        File file = new File(DEST);
        file.mkdirs();

        encryptDecrypt();
    }

    public static void encryptDecrypt() throws GeneralSecurityException, IOException {
        C1_03_EncryptDecrypt app = new C1_03_EncryptDecrypt();
        app.initKeyStore(KEYSTORE, PASSWORD);
        Key publicKey = app.getPublicKey("demo");
        Key privateKey = app.getPrivateKey("demo", "password");

        // Encrypt the message with the public key and then decrypt it with the private key
        System.out.println("Let's encrypt 'secret message' with a public key");
        byte[] encrypted = app.encrypt(publicKey, "secret message");
        System.out.println("Encrypted message: " + app.getDigestAsHexString(encrypted));
        System.out.println("Let's decrypt it with the corresponding private key");
        String decrypted = app.decrypt(privateKey, encrypted);
        System.out.println(decrypted);

        // Encrypt the message with the private key and then decrypt it with the public key
        System.out.println("You can also encrypt the message with a private key");
        encrypted = app.encrypt(privateKey, "secret message");
        System.out.println("Encrypted message: " + app.getDigestAsHexString(encrypted));
        System.out.println("Now you need the public key to decrypt it");
        decrypted = app.decrypt(publicKey, encrypted);
        System.out.println(decrypted);
    }

    private void initKeyStore(String keystore, String ks_pass) throws GeneralSecurityException, IOException {
        ks = KeyStore.getInstance(KeyStore.getDefaultType());
        ks.load(new FileInputStream(keystore), ks_pass.toCharArray());
    }

    private String getDigestAsHexString(byte[] digest) {
        return new BigInteger(1, digest).toString(16);
    }

    private X509Certificate getCertificate(String alias) throws KeyStoreException {
        return (X509Certificate) ks.getCertificate(alias);
    }

    private Key getPublicKey(String alias) throws GeneralSecurityException, IOException {
        return getCertificate(alias).getPublicKey();
    }

    private Key getPrivateKey(String alias, String pk_pass) throws GeneralSecurityException, IOException {
        return ks.getKey(alias, pk_pass.toCharArray());
    }

    // This method encrypts the message (using RSA algorithm) with the key, got as the 1st argument
    public byte[] encrypt(Key key, String message) throws GeneralSecurityException {
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.ENCRYPT_MODE, key);
        byte[] cipherData = cipher.doFinal(message.getBytes());
        return cipherData;
    }

    // This method decrypts the message (using RSA algorithm) with the key, got as the 1st argument
    public String decrypt(Key key, byte[] message) throws GeneralSecurityException {
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.DECRYPT_MODE, key);
        byte[] cipherData = cipher.doFinal(message);
        return new String(cipherData);
    }
}

Il cui output è

Let's encrypt 'secret message' with a public key
 Encrypted message: 18d8b419247c13816563897d0f3cef7ff917be86e7a20528133b7a95377c1690f2326e4cbc9c001e6cb877c5b3645c5f395b4cd48ade4a87651052d09810e4b423aa973c69853c4e0efde238d9b4c038ecd1a53e81b19ce44248ee67056d7d74edb381b29bfc5a7cbad67a147e06e02d7ff65f4fa52718ee7f3265a48c4c146bc0ae98762d57e6b82a77bee31ea1749a47a32c2936df7914d361853c17c46b8064300865c3f763e6a87a1d42594bf254e880b6181946890199e7ffbe26f3f59ce74627594eca7c3a590a4eaa31efeb7d95b2366dd2bafe921c5497bde7e827fa87bec87a26f887434b751555189e3e244f44ea6d63b725709fe8c68ed98c98d8
 Let's decrypt it with the corresponding private key
 secret message
 You can also encrypt the message with a private key
 Encrypted message: 1ecff10fc820eea4647060890ead7669f0f845cb0c42ea8ede8a962d9848dc30bd3ba34113f858264cca1ea195dd30beeff15dae1100c68a75790c0fbba8739791f01a236174e7e1593336def60793713a95c8e4ea53cf1527d73fea52468a11974d8786de7945e3f5e7a0e3f27e6488997811fc6781c4909d27fb0224340a2e40e4e49e5023a5cc9f8531e1ee2d5b763049dac0197b0b252564d1e556a2b5de2c2026c95f94f9de5ea63d95c231c9611eb92736df617474af78c86963d3381738de84d10bf594b07d10edee2aab752c43501cc7356d4cbd0826de2c461828dba4f47bae564defc80b849c27b0dfb1cbbdffabdeb94d71ccff26810986ae2c22
 Now you need the public key to decrypt it
 secret message
 Process finished with exit code 0

Abbiamo quindi cifrato e dicifrato un semlice messaggio “secret message”.

Alla fine, firmiamo il pdf

Posizioniamo il documento da firmare (HelloWorld.pdf) nella directory

./src/test/resources/pdfs/

e lo firmiamo in 4 modi diversi utiizzando gli algoritmi di firma SHA256 (standrd CMS e CADES), SHA512 (CMS) e RIPEMD160 (CADES).

package com.itextpdf.samples.signatures.chapter02;

import com.itextpdf.kernel.geom.Rectangle;
import com.itextpdf.kernel.pdf.PdfReader;
import com.itextpdf.kernel.pdf.StampingProperties;
import com.itextpdf.signatures.*;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.Security;
import java.security.cert.Certificate;

public class C2_01_SignHelloWorld {
    public static final String DEST = "./target/signatures/chapter02/";

    public static final String KEYSTORE = "./src/test/resources/encryption/ks";
    public static final String SRC = "./src/test/resources/pdfs/HelloWorld.pdf";

    public static final char[] PASSWORD = "password".toCharArray();

    public static final String[] RESULT_FILES = new String[] {
            "hello_signed1.pdf",
            "hello_signed2.pdf",
            "hello_signed3.pdf",
            "hello_signed4.pdf"
    };

    public void sign(String src, String dest, Certificate[] chain, PrivateKey pk, String digestAlgorithm,
                     String provider, PdfSigner.CryptoStandard signatureType, String reason, String location)
            throws GeneralSecurityException, IOException {
        PdfReader reader = new PdfReader(src);
        PdfSigner signer = new PdfSigner(reader, new FileOutputStream(dest), new StampingProperties());

        // Create the signature appearance
        Rectangle rect = new Rectangle(36, 648, 200, 100);
        PdfSignatureAppearance appearance = signer.getSignatureAppearance();
        appearance
                .setReason(reason)
                .setLocation(location)

                // Specify if the appearance before field is signed will be used
                // as a background for the signed field. The "false" value is the default value.
                .setReuseAppearance(false)
                .setPageRect(rect)
                .setPageNumber(1);
        signer.setFieldName("sig");

        IExternalSignature pks = new PrivateKeySignature(pk, digestAlgorithm, provider);
        IExternalDigest digest = new BouncyCastleDigest();

        // Sign the document using the detached mode, CMS or CAdES equivalent.
        signer.signDetached(digest, pks, chain, null, null, null, 0, signatureType);
    }

    public static void main(String[] args) throws GeneralSecurityException, IOException {
        File file = new File(DEST);
        file.mkdirs();

        BouncyCastleProvider provider = new BouncyCastleProvider();
        Security.addProvider(provider);
        KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
        ks.load(new FileInputStream(KEYSTORE), PASSWORD);
        String alias = ks.aliases().nextElement();
        PrivateKey pk = (PrivateKey) ks.getKey(alias, PASSWORD);
        Certificate[] chain = ks.getCertificateChain(alias);

        C2_01_SignHelloWorld app = new C2_01_SignHelloWorld();
        app.sign(SRC, DEST + RESULT_FILES[0], chain, pk, DigestAlgorithms.SHA256, provider.getName(),
                PdfSigner.CryptoStandard.CMS, "Prova 1", "Venezia");
        app.sign(SRC, DEST + RESULT_FILES[1], chain, pk, DigestAlgorithms.SHA512, provider.getName(),
                PdfSigner.CryptoStandard.CMS, "Prova 2", "Venezia");
        app.sign(SRC, DEST + RESULT_FILES[2], chain, pk, DigestAlgorithms.SHA256, provider.getName(),
                PdfSigner.CryptoStandard.CADES, "Prova 3", "Venezia");
        app.sign(SRC, DEST + RESULT_FILES[3], chain, pk, DigestAlgorithms.RIPEMD160, provider.getName(),
                PdfSigner.CryptoStandard.CADES, "Prova 4", "Venezia");
    }
}

I file che otteniamo in output sono questi:

Python,MySQL e date

Python logo
Python logo

Sto scrivendo un programma Python che deve inserire in una tabella di un db MySQL alcuni campi letti da un file; alcuni di questi sono di tipo data e sono formattati con il formato “%d-%m-%Y” (per esempio: “25/12/2020”) per cui nel programma devo rovesciare giorno e anno per presentarli a MySQL perché interpret la stringa come una data.

Orbene la seguente riga intesa a svolgere questo compito, non funziona (ometto la definizione della connessione e del cursore):

query = "select str_to_date(substring(%s,1,25), '%d-%m-%Y') data" 
prm=list()
prm.append('16-04-2021')
print(prm)
cur.execute(query, prm)
for row in cur.fetchall():
    print("------------> ",row[0])

Quello che capita è questo:

Traceback (most recent call last):
   File "./mail.py", line 46, in 
     cur.execute(query, prm)
   File "/usr/lib/python3/dist-packages/MySQLdb/cursors.py", line 206, in execute
     raise ProgrammingError(str(m))
 MySQLdb._exceptions.ProgrammingError: not enough arguments for format string

Dov’è che Python si incasina?

Ora, il casino deriva dalla notazione % che si usa sia per i parametri della query SQL che per il formato della data.

Pensavo che il parser ci arrivasse da solo visto che la stringa di formato è racchiusa da virgolette, e invece no. Ingenuo che sono, dopo tanti anni non ho ancora imparato!

Per risolvere questo problema occorre applicare un carattere di escape alla stringa di formato, nel modo seguente

query = "select str_to_date(substring(%s,1,25), '%%d-%%m-%%Y') data" 

Nota il doppio %%.

Facendo così il programma termina correttamente

------------>  2021-04-16

In realtà il formato della data è un po’ più complicato di così, ma l’ho semplificato per circoscrivere il problema.

Risorse web

VPN con Forticlient 6.2.0

vpn
VPN

Un cliente cambia l’infrastruttura di rete privata virtuale e adotta Fortinet.

Finora si era adottata openvpn.

Di seguito trascrivo le istruzioni per installare il client in Ubuntu 20.04.2 LTS focal.

Howto VPN per Ubuntu 18.04 LTS e 20.04 LTS

Scaricare la chiave GPG

wget https://repo.fortinet.com/repo/6.4/ubuntu/DEB-GPG-KEY

Aggiungerla al repository:

sudo apt-key add DEB-GPG-KEY

Aggiungere questa riga in /etc/apt/sources.list

deb [arch=amd64] https://repo.fortinet.com/repo/6.4/ubuntu/ /bionic multiverse

Aggiorna package lists

sudo apt-get update

Installazione FortiClient

sudo apt install forticlient

Procedura 2

La versione scaricata utilizzando sources.list non era compatibile al 100%, sono dunque andato a scricare direttamente il file deb. Prima ho però rimosso la versione appena installata:

sudo apt-get remove forticlient

e poi ho scaricato la versione deb direttamente:

wget https://filestore.fortinet.com/forticlient/downloads/FortiClientFullVPNInstaller_6.4.0.0851.deb

Poi si può procedere ad installarlo

sudo apt install ./FortiClientFullVPNInstaller_6.4.0.0851.deb

A questo punto

$ forticlient
 Starting FortiTray
 Platform detected: ubuntu

Appare la schermata di configurazione della VPN in cui si scrivono l’host del tunnel, la porta, il nome che si vuole dare alla connessione

Impostazioni VPN Fortinet
Impostazioni VPN Fortinet

Ci si connette fornendo username e password:

Client VPN Fortinet
Client VPN Fortinet

e la connessione (se non ci sono altri problemi) viene stabilita:

VPN connessa
VPN connessa

That’s all folks!

Risorse web

Crepa nel Modello Standard

muon-g-2-physics
Precessione di un muone – un modellino

È una cosa che si subodora da vent’anni, ma solo ora c’è un’evidenza molto forte di questo segno di crisi del Modello Standard. Dopo una considerazione introduttiva, riporto il testo integrale dell’annuncio comparso il 7 aprile 2021 sul sito web del Fermilab.

Una premessa: cos’è il Modello Standard?

Il Modello Standard è una teoria di campo che spiega com’è il mondo dal punto di vista microscopico per quanto riguarda le forze fondamentali elettromagnetica, nucleare forte e nucleare debole. La forza gravitazionale non è descritta nel Modello Standard. Esso cataloga in una tabella tutte le particelle fondamentali per tipo (materia – fermioni – o interazione – bosoni) e per famiglia (quark o leptoni). Tuttavia non è solo una semplice tabella quanto un’articolata teoria di campo quantistica che si integra con la Relatività Speciale. Tutto quello che accade in questo reame, da come l’occhio percepisce i colori al bosone di Higgs, è descritto con precisione incredibile da questa teoria.

Ma nella storia ci sono molti esempi di teorie che prevedono tutto ma per le quali arriva un giorno in cui si osserva qualcosa di insapettato.

Buttare via tutto? No, la Fisica è come il maiale, non si butta via niente: c’è solo una classe di fenomeni che per essere spiegata ha bisogno di un’ampliamento della teoria. E generalmente questa nuova teoria getta una luce nuova sul cosmo e ne aumenta la leggibilità e la profondità di interpretazione. Per questo si parla di una Nuova Fisica. Perché ogni volta da una crepa è nata una nuova fisica.

Dall’impossibilità di mettere d’accordo Elettromagnetismo ed il funzionamento del corpo nero è nata la Meccanica Quantistica.

Dall’impossibilità di mettere d’accordo Elettromagnetismo e Meccanica è nata la Teoria Speciale della Relatività.

Dal fatto che la precessione di Mercurio non risultasse così accurata dalle equazioni della Meccanica per un errore di 43″ in un secolo… Be’ qui potete dire: ma che errore è una rotazione 43″ in un secolo? è pedanteria! No! Non lo è. La previsione della teoria e il valore che esce dalla misura possono differire al massimo all’interno dell’incertezza della misura: se la differenza è maggiore c’è qualcosa che non va nella teoria. Ecco… 43″ al secolo era un errore piccolo ma non trascurabile perché più grande dell’errore dello strumento, quindi la Meccanica non spiegava del tutto il fenomeno della precessione più lenta. Qui la Teoria Generale della Relatività invece spiegò benissimo anche quella differenza. A differenza dei casi precedenti la crepa da cui irruppe la Teoria della Reatività Generale non furono quei 43″ d’arco, bensì stavolta la Teoria arrivò da sola a spiegarlo, essendosi evoluta autonomamente nella testa di Albert Einstein.

È curioso che una crepa in una teoria per venga fuori per un fenomeno analogo: la precessione! Anche nel caso del Fermilab c’è una frequenza nella precessione che non torna con quento è previsto dai modelli matematici: i muoni precedono ad una frequenza più alta (dondolano più velocemente) di quella prevista dal Modello Standard.

Come vedrete anche qui la differenza è piccolissima, ma non è trascurabile, perché lo strumento consente una precisione più grande di quell’errore. Nell’articolo non ho toccato la forma, ho solo convertito le unità di misura usate nelle unità del Sistema Internazionale.

Il post integrale sul sito del Fermilab

I risultati, attesi per molto tempo, dell’esperimento Muon g-2 [leggi “g meno 2”] presso il Dipartimento dell’Energia degli Stati Uniti al Fermi National Accelerator Laboratory [Fermilab] mostra particelle fondamentali chiamate muoni che si comportano in un modo non previsto dalla migliore teoria quantistica elaborata dali sceinziati, il Modello Standard della Fisica delle Particelle. Questo risultato di forntiera, svolto con una precisione senza precedenti, conferma una discrepanza su cui i ricercatori stanno rosicando da decenni .

La forte evidenza che i muoni deviano dai calcoli del Modello Standard potrebbe suggerire un’eccitante nuova fisica. I muoni funzionano come una finestra sul mondo subatomico e potrebbero interagire con particelle o forze ancora sconosciute.

“Oggi è un giorno straordinario, atteso a lungo non solo da noi ma da tutta la comunità internazionale di fisici,” ha detto Graziano Venanzoni, co-portavoce dell’esperimento Muon g-2 e fisico dell’Istituto italiano di Fisica Nucleare (INFN). “un grande ringraziamento va ai nostri giovani ricercatori che, con il loro talento, le loro idee e il loro entusiasmo, ci hanno permesso di raggiungere questo incredibile risultato”.

Il muone ha una massa circa 200 volte più grande di quella del suo cugino, l’elettrone. I muoni si trovano in modo naturale nei raggi cosmici che attraversano l’atmosfera terrestre, e gli acceleratori di particelle del Fermilab li possono produrre in grandi quantità. Come gli elettroni, i muoni si comporano come se avessero al loro interno un piccolo magnete. In un campo magnetico intenso, la direzione del muone si muove in precessione, ossia dondola in modo molto simile ad una trottola, o a un giroscopio. L’intensità del magnete interno determina la velocità dell’oscillazione del muone immerso nel campo magnetico esterno ed è descritta con un numero che i fisici chiamano g-factor. Questo numero può essere calcolato con una precisione molto grande.

Fermilab magnetic storage ring per abbattere il Modello Standard
Fermilab magnetic storage ring per mettere alla prova il Modello Standard. I primi risultati dell’esperimento Muon g-2 al Fermilab hanno rafforzato le prove della nuova fisica. Il fulcro dell’esperimento è un anello di accumulo magnetico superconduttore di 15,24 m di diametro (50 piedi), che si trova nella sua sala rivelatori tra rack di elettronica, linea di fascio di muoni e altre apparecchiature. Questo impressionante esperimento opera a una temperatura di 5 K e studia la precessione (o oscillazione) dei muoni mentre viaggiano attraverso il campo magnetico. Foto: Reidar Hahn, Fermilab

Mentre i muoni circolano nel magnete del Muon g-2, essi interagiscono anche con una schiuma quantistica di particelle subatomiche che vengono all’esistenza e scompaiono in continuazione. Le interazioni con queste particelle dalla vita estremamente breve altera il valore del fattore g, causando alla velocità della precessione aumenti e diminuzioni molto piccoli. Il modello standard prevede questo cosiddetto momento magnetico anomalo in modo molto preciso. Ma se la schiuma quantistica contenesse forze addizionali o particelle non prese in considerazione dal Modello Standard, questo modificherebbe in modo ancor più sensibile il valore del fattore g del muone.

“Questa quantità che misuriamo riflette le interazioni del muone con il resto dell’universo. Ma quando i teorici calcolano la stessa quantità, usando tutte le forze conosciute e le particelle del Modello Standard non otteniamo la stessa risposta,” dice Renee Fatemi, una fisica dell’Università del Kentucky e responsabile delle simulazioni per l’esperimento Muon g-2. “Questa è una forte evidenza che il muone è sensibile a qualcosa che la nostra migliore teoria non considera”.

Il precedente esperimento effettuato al Dipartimento dell’Energia degli Stati Uniti presso il Brookhaven National Laboratory, che si concluse nel 2001, suggerì evidenze sulla deviazione del comportamento del muone rispetto a quanto previsto dal Modello Standard. Le nuove misure dal Muon g-2 del Fermilab concordano fortemente con il valore trovato al Brookhaven e deviano dalla teoria con le misure più precise mai eseguite fino ad ora.

L’esperimento Muon g-2 invia un fascio di muoni nell’anello di stoccaggio, nel quale compiono migliaia di giri ad una velocità prossima a quella della luce. I rivelatori che rivestono l’anello permettono agli scienziati di determinare a quanto ammonti la precessione dei muoni.

Nel suo primo anno di funzionamento, nel 2018, l’esperimento del Fermilab ha raccolto più dati di tutti i dati insieme usciti dagli esperimenti sul fattore g del muone fatti fino a quel momento. Con più di 200 scienziati da 35 istituzioni di sette nazioni, la collaborazione Muon g-2 ha ora terminato l’analisi del moto di più di 8 miliardi di muoni dal primo lancio dell’esperimento.

“Dopo i 20 anni trascorsi dalla fine dell’esperimento di Brookhaven, è così gratificante poter finalmente risolvere questo mistero”, ha detto lo scienziato del Fermilab Chris Polly, co-portavoce dell’attuale esperimento e che era lo studente principale che si è laureato sull’esperimento di Brookhaven.

L’analisi dei dati sulla seconda e terza esecuzione dell’esperimento è in corso, la quarta esecuzione è in corso ed è prevista una quinta esecuzione. La combinazione dei risultati di tutte e cinque le analisi darà agli scienziati una misurazione ancora più precisa dell’oscillazione del muone, rivelando con maggiore certezza se la nuova fisica si nasconde all’interno della schiuma quantistica.

“Finora abbiamo analizzato meno del 6% dei dati che alla fine l’esperimento raccoglierà. Anche se questi primi risultati ci dicono che c’è una differenza interessante con il modello standard, impareremo molto di più nei prossimi due anni “, ha detto Polly.

Differenza per il valore g tra Modello Standard e risultati sperimentali
Differenza per il valore g tra Modello Standard e risultati sperimentali. Il primo risultato dell’esperimento Muon g-2 al Fermilab conferma il risultato dell’esperimento condotto al Brookhaven National Lab due decenni fa. Insieme, i due risultati mostrano una forte evidenza che i muoni divergono dalla previsione del modello standard. Immagine: Ryan Postel, collaborazione Fermilab / Muon g-2

I valori teorici accettati per il muone sono
g-factor: 2,00233183620(86)
momento magnetico anomalo: 0,00116591810(43)
(l’incertezza è tra parentesi)

I nuovi valori medi sperimentali annunciati oggi [7 aprile 2021] dalla collaborazione Muon g-2 sono:
g-factor: 2.00233184122(82)
momento magnetico anomalo: 0.00116592061(41)

I risultati combinati dal Fermilab e Brookhaven mostrano una differenza con la teoria di una significatività di 4,2 sigma, un 5-sigma “timido” [1 sigma = 1 deviazione standard] che gli scienziati richiedono per annunciare una scoperta, ma una forte indicazione dell’evidenza di una nuova fisica. La probabilità che i risultati siano solo una fluttuazione statistica è di 1 su 40.000.

L’esperimento del Fermilab riutilizza il componente principale dell’esperimento di Brookhaven, un anello superconduttore magnetico di circa 15 metri di diametro. Nel 2013 fu trasportato per più di 5000 km via terra e via mare da Long Island alla periferia di Chicago, dove gli scienziati hanno potuto trarre vantaggio dall’acceleratore di particelle del Fermilab e produrre il fascio di muoni più intenso degli Stati Uniti. Nei successivi quattro anni, i ricercatori hanno assemblato l’esperimento, messo a punto e calibrato un campo magnetico incredibilmente uniforme; sviluppato nuove tecniche, strumenti e testato a fondo l’intero sistema.

Fonte

Pillole Oracle: scovare e ricompilare oggetti invalidati

oracle
Oracle logo

Ogni tanto capita che in seguito ad operazioni di modifica di programmi Oracle, alcuni oggetti da questi dipendenti risultino invalidati. Di solito, invocando questi oggetti con un client risulta in un errore a runtime.

L’istruzione che permette di trovare lo stato degli oggetti è il seguente e deve essere lanciato da un utente con privilegi di DBA:

select
   comp_id,
   comp_name,
   version,
   status,
   namespace,
   schema
from
   dba_registry;

Uno script che individua gli oggetti (packages PL/SQL, procedure, funzioni e corpi di package) è invece il seguente

invalid.sql

Set heading off;
set feedback off;
set echo off;
Set lines 999;
Spool run_invalid.sql

select
	'ALTER ' || OBJECT_TYPE || ' ' ||
	 OWNER || '.' || OBJECT_NAME || ' COMPILE;'
from
	 dba_objects
where
	 status = 'INVALID'
and
	 object_type in ('PACKAGE','FUNCTION','PROCEDURE');

spool off;

set heading on;
set feedback on;
set echo on;

@run_invalid.sql

Link utili

Altri post sull’argomento

LibreOffice in pillole: il plugin MacroFormatterADP

Tra i molti plugin disponibili per Libreoffice, vi volevo illustrare MacroFormatterADP, un programma di formattazione del testo utile per evidenziare testo che costituisce un brano di un codice sorgente di un linguaggio di programmazione.

MacroFormatterADP: come installarlo

Il plugin MacroFormatterADP è disponibile a questo URL. È stato sviluppato da Andrew Pitonyak.

Come prima operazione, scaricate il pacchetto cliccando su Download e mettetelo in una cartella che ricordate.

Dal menu Strumenti cliccare su Gestione estensioni… si apre la finestra seguente

Libreoffice macrofromatterADP
gestione estensioni

Cliccate su Aggiungi, cercate il plugin appena scaricato nel disco e cliccate su Apri. L’installazione è fatta.

Cliccando su Scarica altre estensioni, accederete al sito di Libreoffice nella galleria completa di tutti i plugin disponibili: divertitevi!

Come usare MacroFormatterADP

Nel frattempo (da quando io l’ho installato qualche tempo fa) il plugin ha cambiato nome ed è diventato Code Colorizer Formatter ed è selezionabile evidenziando il testo da formattare e lanciandolo dal menu, come nella figura che segue:

macroformatter

Il risultato finale è il seguente

formatted

La formattazione con evidenzia della sintassi è molto gradevole.

Linguaggi disponibili

I linguaggi di programmazione in cui è possibile formattare sono i seguenti:

  • BASH,
  • Basic,
  • Bat
  • C++,
  • Go,
  • Java,
  • Perl,
  • PHP,
  • Python,
  • R,
  • Rust,
  • SQL,
  • XML,
  • C#,
  • Lisp,
  • Object C,
  • JavaScript,
  • Ruby,
  • 8085 Assembler, and
  • x86 Assembler.

È un plugin molto utile per documentazione tecnica che deve contenere alcuni estratti di codice sorgente, rende il documento leggibile come se stesse utilizzando una IDE.

Altri post su LibreOffice

Perseverance atterra su Marte

Il veicolo terrestre (rover) Perseverance che esplorerà i dintorni del cratere Jezero nell’ambito della missione Mars 2020, del Mars Exploration Program, è atterrato venerdì 18 febbraio 2021 alle 3:55 PM EST (le 21:55 in Italia) dopo aver percorso una traiettoria di 472 milioni di km in 203 giorni.

Va ad aggiungersi agli altri quattro rover che già sono su Marte: Pathfinder /Sojourner (1997) Spirit e Opportunity (2003) e Curiosity (2011). Però in più avrà un compagno di avventure: il drone Ingenuity.

Perseverance priam immagine dopo il landing
Questa è la prima immagine che il rover Perseverance della NASA ha inviato appena dopo essere atterrato su Marte il 18 febbraio 2021. La vista, da una delle telecamere di sicurezza di Perseverance, è parzialmente oscurata da una copertura antipolvere. Credits: NASA / JPL-Caltech.

Il rover, che ha una massa di 1026 kg ed è dotato di strumentazione con funzionalità di geologia e astrobiologia, percorrerà un cammino nei pressi del cratere Jezero, un cartere di 45 km di diametro formatosi 3,5 miliardi di anni fa, che gli scienziati ritengono fosse diventato il letto di un lago vulcanico (come il nostro lago di Bracciano) con un affluente con estuario a delta per studiarne le caratteristiche geologiche e tracce del clima antico. Contemporaneamente il laboratorio di astrobiologia cercherà tracce di microbi antichi.

I campioni prelevati da Perseverance verranno successivamente riportati a Terra da una seconda missione pianificata da NASA e ESA. Anche questa è una attività finora mai intrapresa.

Un vantaggio di questo di tipo di missione è che la strumentazione inviata è praticamente lo stato dell’arte in fatto di ricerca spaziale. Infatti il tempo di volo è di pochi mesi. Per missioni più lontane come quelle sui pianeti esterni, quando la sonda raggiunge l’obiettivo, la stumentazione a bordo è già obsoleta rispetto a quanto nel frattempo si è risuciti a produrre sulla Terra.

Strumentazione di bordo

La strumentazione di bordo è eccezionale: comprende, tra tutti i dispositivi installati:

  • una coppia di telecamere scientifiche Mastcam-Z, che costituiscono il sistema di visione e guida del rover e che possono ritrarre foto panoramiche steroscopiche a colori ad alta risoluzione,
  • il sistema MEDLI2 che contiene la strumentazione di ingresso in atmosfera, discesa e atterraggio come strumentazione di analisi dell’atmosfera
  • il sistema di collezione di reperti geologici Sample Gathering System,
  • il sistema SHERLOC (Scanning Habitable Environments with Raman & Luminescence for Organics & Chemicals ovvero il sistema indagine di ambienti abiltabili tramite la rilevazione di luminescenza e diffusione di Raman, da applicarsi a reperti chimici e biologici).
  • il sistema MOXIE (Mars Oxygen In-Situ Resource Utilization Experiment) che tenterà di generare ossigeno – l’atmosfera marziana è composta al 95% di CO2 e solo del 0,13% di ossigeno.
  • il RIMFAX (Radar Imager for Mars’ Subsurface Experiment) che usa una tecnologia Radar per esplorare il sottosuolo.

Per fare funzionare tutto questo laboratorio – e per portarlo in giro per il pianeta! – e far funzionare le trasmissioni radio c’è un generatore termoelettrico a radioisotopi multi missione (MMRTG) – un motore atomico che converte l’energia emessa dal decadimento di Plutonio-238 in elettricità attraverso il riscaldamento di una termocoppia – che gli consentirà di coprire un tragitto molto lungo, come illustrato nella prossima immagine:

Perseverance: il viaggio attorno al cratere Jezero.
Questa sovrapposizione di fotografie annotata raffigura un possibile percorso che il rover Mars 2020 Perseverance potrebbe intraprendere attraverso il cratere Jezero mentre indaga su diversi ambienti antichi che potrebbero essere stati abitabili. Credits: NASA/JPL-Caltech

La mascotte di Perseverance: Ingenuity

Tuttavia l’esplorazione marziana di Perseverance potrà iniziare soltanto a test conclusi sia per il rover (verranno effettuati test sulla strumentazione e sul software) e anche i test per il piccolo drone, o meglio l’elicottero marziano, Ingenuity (ingegnosità in Italiano, è un false friend :-)).

Questo elicottero usa dei motori che, per produrre una spinta sufficiente a tenerlo in volo, vengono fatti girare ad una velocità superiore a quella che sarebbe sufficiente sulla Terra per via della rarefazione dell’atmosfera di Marte. Infatti la pressione atmosferica media su Marte è di circa 7 hPa, mentre quella media sulla Terra è di circa 1013 hPa.

Per fare un paragone, la pressione al suolo di Marte è all’incirca quella che presenta l’atmosfera sulla Terra a 40 km di altezza.

L’importanza di Ingenuity è quella di costituire il primo esperimento di volo controllato in un’atomosfera non terrestre.

Ingenuity: Mars Helicopter Technology Demostration – il primo esperimento di volo controllato in atmosfera extraterrestre.
Credits: NASA/JPL-Caltech

Link utili