Java
Java
BackView
If you think about taking backups it might be attractive to use hardlinks see rsync or cp -al. A basic overview is possible with du -hs as it shows the amount of space taken by a backup (it counts the inodes in selection only once). But to allow a bit more insight, the following Java-Program might be helpful to see what was backed up when:
Java sources
Simple method to check variation of directories using hard-links:
public int[] test(File dir, Map<Object, String> inodes) throws IOException { int add = 0,del = 0; File[] files = dir.listFiles(); Map<Object, String> inodesLocal = new HashMap<>(); for (File file : files) { Path path = file.toPath(); PosixFileAttributes attr = Files.readAttributes(path, PosixFileAttributes.class); String prev = inodes.get(attr.fileKey()); if (prev == null) { add++; } inodesLocal.put(attr.fileKey(), file.getAbsolutePath()); } inodes.keySet().removeAll(inodesLocal.keySet()); del = inodes.size(); inodes.clear(); inodes.putAll(inodesLocal); return new int[] {add, del}; }
To access the inode value directly one may use:
Map<String, Object> attrs = Files.readAttributes(path, "unix:*");
and check the value "ino".
Covid
If you are looking for some informations about the digital Eu-certificat (Qr-code) the Android App repository might be helpful.
Information on digital-certificat RKI impf-app.
The rfc8152 (abstract) definition of the certificat format (COSE).
Or if you just want to have a look on some simple Java example on a vaccination use the following Maven/(Netbeans) project (with CertInfo input_image). Requires a scanned Qr-code image, allows rewriting the Qr-Code-Copy as backup (with CertInfo input_image output.png)... the testing/recovery information shoud be easy to add, but i had non of these available. Used java-green pass as a starting point.
Lexical sorting
My suggestion for a lexical sorting extended from (which implements DIN 5007):
private static void sort(List<String> strs, Collator coll) { List<String> cstrs = new ArrayList<>(strs); Collections.sort(cstrs, coll); String prev = ""; for (String str : cstrs) { System.out.format(" %s %d\n", str, coll.compare(str, prev)); prev = str; } } private static final String EXT_RULES = "< ' ' < '.'"+ "<0<1<2<3<4<5<6<7<8<9<a & ae,ä,A & AE,Ä<b,B<c,C<d,D<ð,Ð<e,E<f,F<g,G<h,H<i,I<j"+ ",J<k,K<l,L<m,M<n,N<o & oe,ö,O & OE,Ö<p,P<q,Q<r,R<s, S & SS,ß<t,T& TH, Þ &TH,"+ "þ <u & ue,ü,U & UE,Ü<v,V<w,W<x,X<y,Y<z,Z&AE,Æ&AE,æ&OE,Œ&OE,œ"; public static void main(String[] args) throws Exception { List<String> strs = new ArrayList<>(); RuleBasedCollator deCol = (RuleBasedCollator)Collator.getInstance(Locale.GERMAN); Collator col = new RuleBasedCollator(deCol.getRules() + EXT_RULES); col.setStrength(Collator.PRIMARY); strs.add("haber"); strs.add("Hafen"); strs.add("Härten"); strs.add("Härte"); strs.add("Haerte"); strs.add("Haber"); strs.add("Mohshärte"); strs.add("Mörtel"); strs.add("Modulation"); sort(strs, col);
Result (the number indicates if it is considered less/greater or equal to previous value):
haber 1 Haber 0 Härte 1 Haerte 0 Härten 1 Hafen 1 Modulation 1 Mörtel 1 Mohshärte 1
Alternative Jdk source
Bedwork
Use java8
git clone https://github.com/Bedework/bw-caldav.git --branch bw-caldav-4.0.7
Interface to implement backend:
org.bedework.caldav.server.sysinterface.SysIntf
Servlet template:
bw-calendar-engine-ucaldav
Default impl override by out impl?
bw-calendar-engine-impl
Level | Modul | |
---|---|---|
0 | bw-util-loggin-5.01 | |
1 | bw-util-misc-4.0-32 | |
2 |
Maven install locally:
cd /home/rpf/bedework/bw-util2/bw-util2-calendar; JAVA_HOME=/usr/lib/jvm/default /usr/local/netbeans/java/maven/bin/mvn -DartifactId=bw-xml-icalendar -DgroupId=org.bedework -Dversion=4.0.10 -Dpackaging=jar -Dfile=/home/rpf/bedework/bw-xml/bw-xml-icalendar/target/bw-xml-icalendar-4.0.12-SNAPSHOT.jar -DgeneratePom=false install:install-file
This is something for the academic interested.
Cosmo
Some workable solution for Java8 (no CardDav).
https://github.com/1and1/cosmo
Crypto with AES
As it seems the compatibility of open-ssl and Java is no that easy here a example:
/* * Copyright (C) 2022 rpf * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package de.pfeifer_syscon.work.codeAES; import java.nio.charset.Charset; import java.security.SecureRandom; import java.security.spec.KeySpec; import java.util.Base64; import javax.crypto.Cipher; import javax.crypto.SecretKey; import javax.crypto.SecretKeyFactory; import javax.crypto.spec.GCMParameterSpec; import javax.crypto.spec.PBEKeySpec; import javax.crypto.spec.SecretKeySpec; /** * a openssl compatible AES en-/decyption * * @author rpf */ public class Crypt { public byte[] decodeBase64(String src) throws Exception { Base64.Decoder dec = Base64.getDecoder(); byte[] decoded = dec.decode(src); return decoded; } public String encodeBase64(byte[] src) throws Exception { Base64.Encoder enc = Base64.getEncoder(); byte[] encoded = enc.encode(src); return new String(encoded, Charset.forName("ASCII")); } public byte[] decrypt(byte[] cipherText, String add, SecretKey key, byte[] iv, byte[] tag) throws Exception { // Get Cipher Instance Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding"); // Create GCMParameterSpec GCMParameterSpec gcmParameterSpec = new GCMParameterSpec(tag.length * 8, iv); // Initialize Cipher for DECRYPT_MODE cipher.init(Cipher.DECRYPT_MODE, key, gcmParameterSpec); // additional cipher.updateAAD(add.getBytes(Charset.forName("UTF-8"))); // Perform Decryption cipher.update(cipherText); byte[] decrypted = cipher.doFinal(tag); // the tag is required on be in final return decrypted; } public byte[] encrypt(byte[] plainText, String add, SecretKey key, byte[] iv, byte[] tag) throws Exception { // Get Cipher Instance Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding"); // Create GCMParameterSpec GCMParameterSpec gcmParameterSpec = new GCMParameterSpec(tag.length * 8, iv); // Initialize Cipher for ENCRYPT_MODE cipher.init(Cipher.ENCRYPT_MODE, key, gcmParameterSpec); // additional cipher.updateAAD(add.getBytes(Charset.forName("UTF-8"))); // Perform encryption byte[] enc = cipher.update(plainText); // any full block will be returned here byte[] realEnc = new byte[plainText.length]; // assumption encoded has same length (may change if algo/padding changes) if (enc != null) { System.arraycopy(enc, 0, realEnc, 0, enc.length); // use as much as we get here } byte[] remain = cipher.doFinal(); // here the last incomplete block and the tag is returned System.arraycopy(remain, 0, realEnc, enc != null ? enc.length : 0, remain.length - tag.length); System.arraycopy(remain, remain.length - tag.length, tag, 0, tag.length); // and return tag of the requested size return realEnc; } private SecretKey getSecret(String passphrase, byte[] saltBytes, int iter) throws Exception { SecretKeyFactory secFactory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256"); KeySpec spec = new PBEKeySpec(passphrase.toCharArray(), saltBytes, iter, 256); return new SecretKeySpec(secFactory.generateSecret(spec).getEncoded(), "AES"); } /* * Example: * Salt ICAYGYLMoJg7V1BQDdEYlw== keyIter 1024 * Encrypted dxy/6lf5lXnv2/kL4QLcha82ZOtzhUmPHKUvlk+Tfe5+y2nwNjDCe4YYZBYWiFuLI7Ctp21cQ9neF+N37HI1B3iGEf08Ag== tag sGayvykFzE/IpQPgaOb0ZA== * Decrypted abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789öäüß */ public static void main(String[] args) { try { Crypt crypt = new Crypt(); String passphrase = "passphraseÖÄÜ"; byte[] salt = new byte[16]; SecureRandom random = new SecureRandom(); random.nextBytes(salt); int keyIter = 1024; SecretKey secretKey = crypt.getSecret(passphrase, salt, keyIter); System.out.format("Salt %s keyIter %d\n", crypt.encodeBase64(salt), keyIter); String plain = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789öäüß"; String add = "name"; // ensures that a encryption for a diffrent context may not be exchanged byte[] iv = new byte[12]; random.nextBytes(iv); byte[] tag = new byte[16]; byte[] encrypt = crypt.encrypt(plain.getBytes(Charset.forName("UTF-8")), add, secretKey, iv, tag); System.out.format("Encrypted %s tag %s\n", crypt.encodeBase64(encrypt), crypt.encodeBase64(tag)); byte[] decrypt = crypt.decrypt(encrypt, add, secretKey, iv, tag); String text = new String(decrypt, Charset.forName("UTF-8")); System.out.format("Decrypted %s \n", text); } catch (Exception exc) { exc.printStackTrace(); } } }
And now c++ header
/* * Copyright (C) 2022 rpf * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ #pragma once #include <string> #include <memory> #include <openssl/evp.h> class CryptException : public std::exception { public: CryptException(const std::string &what); virtual ~CryptException(); virtual const char* what() const throw(); private: std::string m_what; }; class CryptBuf { public: CryptBuf(); CryptBuf(size_t size); CryptBuf(const std::string& base64); virtual ~CryptBuf(); CryptBuf& operator=(const CryptBuf& other); void setSize(size_t size); size_t getSize() const; unsigned char *getBuf() const; void rand(); void dump(); std::string base64(); private: size_t m_size; unsigned char *m_buf; }; class CryptHmac { public: CryptHmac(const std::string& secret, size_t iter); CryptHmac(const std::string& secret, const std::string& saltBase64, size_t iter); virtual ~CryptHmac(); std::shared_ptr<CryptBuf> getKey() const; std::shared_ptr<CryptBuf> getSalt() const; size_t getIterations() const; protected: CryptHmac(size_t iter); void generateKey(const std::string& secret); private: const EVP_MD *m_mdigest; size_t m_iterations; std::shared_ptr<CryptBuf> m_key; std::shared_ptr<CryptBuf> m_salt; }; class CryptMessage { public: CryptMessage(const std::string& message, const std::string& additional, const CryptHmac& cryptHmac); CryptMessage(const std::string& ivBase64, const std::string& cipherTextBase64, const std::string& additional, const CryptHmac& cryptHmac, const std::string& tagBase64); virtual ~CryptMessage(); int encrypt(unsigned char *plaintext, int plaintext_len, unsigned char *aad, int aad_len, unsigned char *ciphertext); int decrypt(unsigned char *ciphertext, int ciphertext_len, unsigned char *aad, int aad_len, unsigned char *plaintext); int randIV(); int setIV(const unsigned char *iv); const std::shared_ptr<CryptBuf> getIV(); const std::shared_ptr<CryptBuf> getCipherText(); const std::string getPlainText(); const std::shared_ptr<CryptBuf> getTag(); protected: CryptMessage(); private: void handleErrors(void); std::shared_ptr<CryptBuf> m_key; std::shared_ptr<CryptBuf> m_iv; std::shared_ptr<CryptBuf> m_tag; const EVP_CIPHER *m_cipher; std::shared_ptr<CryptBuf> m_ciphertext; std::shared_ptr<CryptBuf> m_plaintext; };
c++ source
/* * Copyright (C) 2022 rpf * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ #include <glibmm.h> #include <openssl/conf.h> #include <openssl/err.h> #include <openssl/rand.h> #include <stdio.h> #include <iostream> #include <cstring> #include "Crypt.hpp" CryptException::CryptException(const std::string &what) : m_what{what} { } CryptException::~CryptException() { } const char* CryptException::what() const throw() { return m_what.c_str(); } CryptBuf::CryptBuf() : m_size(0u) , m_buf{nullptr} { } CryptBuf::CryptBuf(size_t size) : CryptBuf() { setSize(size); } CryptBuf::CryptBuf(const std::string& base64) : CryptBuf() { int size = base64.length() / 4 * 3; setSize(size); int ret = EVP_DecodeBlock(m_buf, (const unsigned char *)base64.c_str(), base64.length()); if (ret < 0) { throw CryptException(Glib::ustring::sprintf("Error EVP_DecodeBlock size %d\n", size)); } // remove padding if (base64.length() > 2 && base64.substr(base64.length()-2) == "==") { m_size -= 2; } else if (base64.length() > 1 && base64.substr(base64.length()-1) == "=") { m_size--; } } CryptBuf& CryptBuf::operator=(const CryptBuf& other) { setSize(other.getSize()); memcpy(m_buf, other.getBuf(), other.getSize()); return *this; } CryptBuf::~CryptBuf() { if (m_buf) { delete[] m_buf; m_buf = nullptr; } } void CryptBuf::setSize(size_t size) { if (size != m_size) { if (m_buf) { delete[] m_buf; m_buf = nullptr; } if (size > 0) { m_buf = new unsigned char[size]; } m_size = size; } } size_t CryptBuf::getSize() const { return m_size; } unsigned char * CryptBuf::getBuf() const { return m_buf; } void CryptBuf::rand() { if (!m_buf) { throw CryptException(Glib::ustring::sprintf("Error gen rand no buf size %d\n", m_size)); } if (1 != RAND_bytes(m_buf, m_size)) { throw CryptException(Glib::ustring::sprintf("Error gen rand %d\n", m_size)); } } void CryptBuf::dump() { BIO_dump_fp(stdout, (const char *)m_buf, m_size); } std::string CryptBuf::base64() { if (!m_buf) { throw CryptException(Glib::ustring::sprintf("Error gen rand no buf size %d\n", m_size)); } uint8_t* base64 = new uint8_t[(m_size / 3 + 1) * 4 + 1]; // 3bytes eventually padded will result in 4bytes base64 plus closing '\0' if (!base64) { throw CryptException(Glib::ustring::sprintf("Error alloc base64 buf size %d\n", m_size)); } EVP_EncodeBlock(base64, m_buf, m_size); std::string data((const char *)base64); delete[] base64; return data; } CryptHmac::CryptHmac(size_t iter) : m_mdigest{EVP_sha256()} , m_iterations{iter} , m_key{std::make_shared<CryptBuf>(32u)} , m_salt{std::make_shared<CryptBuf>(32u)} { } CryptHmac::CryptHmac(const std::string& secret, size_t iter) : CryptHmac{iter} { m_salt->rand(); generateKey(secret); } CryptHmac::CryptHmac(const std::string& secret, const std::string& saltBase64, size_t iter) : CryptHmac{iter} { m_salt = std::make_shared<CryptBuf>(saltBase64); generateKey(secret); } CryptHmac::~CryptHmac() { } size_t CryptHmac::getIterations() const { return m_iterations; } void CryptHmac::generateKey(const std::string& secret) { const char* cpass = (const char*)secret.c_str(); size_t pass_len = strlen(cpass); int ret = PKCS5_PBKDF2_HMAC(cpass, pass_len, m_salt->getBuf(), m_salt->getSize(), m_iterations, m_mdigest, m_key->getSize(), m_key->getBuf()); if (1 != ret) { throw CryptException(Glib::ustring::sprintf("PKCS5_PBKDF2_HMAC failed, error 0x%lx\n", ERR_get_error())); } } std::shared_ptr<CryptBuf> CryptHmac::getKey() const { return m_key; } std::shared_ptr<CryptBuf> CryptHmac::getSalt() const { return m_salt; } CryptMessage::CryptMessage() : m_key{std::make_shared<CryptBuf>(32u)} // the recommendation is to use 12bytes as additional seems not to improve anything // https://crypto.stackexchange.com/questions/26783/ciphertext-and-tag-size-and-iv-transmission-with-aes-in-gcm-mode/26787#26787?newreg=3942556a7f664d16a466b114e0fc993e , m_iv{std::make_shared<CryptBuf>(12u)} , m_tag{std::make_shared<CryptBuf>(16u)} , m_cipher{EVP_aes_256_gcm()} , m_ciphertext{} , m_plaintext{} { } CryptMessage::CryptMessage(const std::string& message, const std::string& additional, const CryptHmac& cryptHmac) : CryptMessage{} { m_key = cryptHmac.getKey(); m_iv->rand(); /* * Buffer for ciphertext. Ensure the buffer is long enough for the * ciphertext which may be longer than the plaintext, depending on the * algorithm and mode. */ m_ciphertext = std::make_shared<CryptBuf>(message.length()); // for aes this shoud equal the input size /* Encrypt the plaintext */ int ciphertext_len = encrypt((uint8_t *)message.c_str(), message.length(), (uint8_t *)additional.c_str(), additional.length(), m_ciphertext->getBuf()); if (message.length() != ciphertext_len) { fprintf(stderr, "Unexpected length cipher %d expected %d\n", ciphertext_len, message.length() ); } /* Do something useful with the ciphertext here */ //printf("Ciphertext is:\n"); //m_ciphertext->dump(); //printf("Tag is:\n"); //m_tag->dump(); } CryptMessage::CryptMessage(const std::string& ivBase64, const std::string& cipherTextBase64, const std::string& additional, const CryptHmac& cryptHmac, const std::string& tagBase64) : CryptMessage() { m_key = cryptHmac.getKey(); m_iv = std::make_shared<CryptBuf>(ivBase64); //printf("iv is:\n"); //m_iv->dump(); m_tag = std::make_shared<CryptBuf>(tagBase64); m_ciphertext = std::make_shared<CryptBuf>(cipherTextBase64); m_plaintext = std::make_shared<CryptBuf>(m_ciphertext->getSize() + 1); /* Decrypt the ciphertext */ int decryptedtext_len = decrypt(m_ciphertext->getBuf(), m_ciphertext->getSize(), (uint8_t *)additional.c_str(), additional.length(), m_plaintext->getBuf()); if (decryptedtext_len >= 0) { /* Add a NULL terminator. We are expecting printable text */ m_plaintext->getBuf()[decryptedtext_len] = '\0'; /* Show the decrypted text */ //printf("Decrypted text is:\n"); //printf("%s\n", m_plaintext->getBuf()); } else { printf("Decryption failed\n"); } } CryptMessage::~CryptMessage() { } void CryptMessage::handleErrors(void) { ERR_print_errors_fp(stderr); } int CryptMessage::setIV(const unsigned char *iv) { memcpy(m_iv->getBuf(), iv, m_iv->getSize()); return 1; } const std::shared_ptr<CryptBuf> CryptMessage::getIV() { return m_iv; } const std::shared_ptr<CryptBuf> CryptMessage::getCipherText() { return m_ciphertext; } const std::string CryptMessage::getPlainText() { std::string text((const char*)m_plaintext->getBuf()); return text; } const std::shared_ptr<CryptBuf> CryptMessage::getTag() { return m_tag; } int CryptMessage::encrypt(unsigned char *plaintext, int plaintext_len, unsigned char *aad, int aad_len, unsigned char *ciphertext) { EVP_CIPHER_CTX *ctx; /* Create and initialise the context */ if(!(ctx = EVP_CIPHER_CTX_new())) { handleErrors(); throw CryptException(Glib::ustring::sprintf("Error EVP_CIPHER_CTX_new %d", ERR_get_error())); } /* Initialise the encryption operation. */ if(1 != EVP_EncryptInit_ex(ctx, m_cipher, NULL, NULL, NULL)) { handleErrors(); throw CryptException(Glib::ustring::sprintf("Error EVP_EncryptInit_ex %d", ERR_get_error())); } /* * Set IV length if default 12 bytes (96 bits) is not appropriate * so raised this value from 128 to 256 */ if(1 != EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, m_iv->getSize(), NULL)) { handleErrors(); throw CryptException(Glib::ustring::sprintf("Error EVP_EncryptInit_ex size %d", m_iv->getSize())); } /* Initialise key and IV */ if(1 != EVP_EncryptInit_ex(ctx, NULL, NULL, m_key->getBuf(), m_iv->getBuf())) { handleErrors(); throw CryptException(Glib::ustring::sprintf("Error EVP_EncryptInit_ex %d", ERR_get_error())); } /* * Provide any AAD data. This can be called zero or more times as * required */ int len; if(1 != EVP_EncryptUpdate(ctx, NULL, &len, aad, aad_len)) { handleErrors(); throw CryptException(Glib::ustring::sprintf("Error EVP_EncryptUpdate add len %d", aad_len)); } /* * Provide the message to be encrypted, and obtain the encrypted output. * EVP_EncryptUpdate can be called multiple times if necessary */ if(1 != EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, plaintext_len)) { handleErrors(); throw CryptException(Glib::ustring::sprintf("Error EVP_EncryptUpdate plain len %d", plaintext_len)); } int ciphertext_len = len; /* * Finalise the encryption. Normally ciphertext bytes may be written at * this stage, but this does not occur in GCM mode */ if(1 != EVP_EncryptFinal_ex(ctx, ciphertext + len, &len)) { handleErrors(); throw CryptException(Glib::ustring::sprintf("Error EVP_EncryptFinal_ex %d", ERR_get_error())); } ciphertext_len += len; /* Get the tag */ if(1 != EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, m_tag->getSize(), m_tag->getBuf())) { handleErrors(); throw CryptException(Glib::ustring::sprintf("Error EVP_CIPHER_CTX_ctrl tag len %d", m_tag->getSize())); } /* Clean up */ EVP_CIPHER_CTX_free(ctx); return ciphertext_len; } int CryptMessage::decrypt(unsigned char *ciphertext, int ciphertext_len, unsigned char *aad, int aad_len, unsigned char *plaintext) { EVP_CIPHER_CTX *ctx; /* Create and initialise the context */ if(!(ctx = EVP_CIPHER_CTX_new())) { handleErrors(); throw CryptException(Glib::ustring::sprintf("Error EVP_CIPHER_CTX_new %d", ERR_get_error())); } /* Initialise the decryption operation. */ if(!EVP_DecryptInit_ex(ctx, m_cipher, NULL, NULL, NULL)) { handleErrors(); throw CryptException(Glib::ustring::sprintf("Error EVP_DecryptInit_ex %d", ERR_get_error())); } /* Set IV length. Not necessary if this is 12 bytes (96 bits) */ if(!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, m_iv->getSize(), NULL)) { handleErrors(); throw CryptException(Glib::ustring::sprintf("Error EVP_CIPHER_CTX_ctrl ivlen %d", m_iv->getSize())); } /* Initialise key and IV */ if(!EVP_DecryptInit_ex(ctx, NULL, NULL, m_key->getBuf(), m_iv->getBuf())) { handleErrors(); throw CryptException(Glib::ustring::sprintf("Error EVP_DecryptInit_ex %d", ERR_get_error())); } /* * Provide any AAD data. This can be called zero or more times as * required * this provides some context, and prevents the message to be * decoded from a different context */ int len; if(!EVP_DecryptUpdate(ctx, NULL, &len, aad, aad_len)) { handleErrors(); throw CryptException(Glib::ustring::sprintf("Error EVP_DecryptUpdate add len %d", aad_len)); } /* * Provide the message to be decrypted, and obtain the plaintext output. * EVP_DecryptUpdate can be called multiple times if necessary */ if(!EVP_DecryptUpdate(ctx, plaintext, &len, ciphertext, ciphertext_len)) { handleErrors(); throw CryptException(Glib::ustring::sprintf("Error EVP_DecryptUpdate cipher len %d", ciphertext_len)); } int plaintext_len = len; /* Set expected tag value. Works in OpenSSL 1.0.1d and later */ if(!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, m_tag->getSize(), m_tag->getBuf())) { handleErrors(); throw CryptException(Glib::ustring::sprintf("Error EVP_CIPHER_CTX_ctrl tag len %d", m_tag->getSize())); } /* * Finalise the decryption. A positive return value indicates success, * anything else is a failure - the plaintext is not trustworthy. */ int ret = EVP_DecryptFinal_ex(ctx, plaintext + len, &len); /* Clean up */ EVP_CIPHER_CTX_free(ctx); if(ret > 0) { /* Success */ plaintext_len += len; return plaintext_len; } else { handleErrors(); throw CryptException(Glib::ustring::sprintf("Error EVP_DecryptFinal_ex len %d", len)); } } /* * Example * Salt T7oYH7CnLegoPK/quz9QiQ== keyIter 1024 * Encrypted bGD1NlfxA5+tzbSUHIMF9lmNBQcxcBuD3cS44CAn/x0uzQoq0IRSYz/svOzLlv2yU69uZ4gKEBsirrHNKt0Go4P7FH01cw== tag nUUTAs/aB8D3NsKSlJZ5og== * Decrypted abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789öäüß */ int main(int argc, char** argv) { try { Glib::ustring passphrase(u8"passphraseÖÄÜ"); auto salt = std::make_shared<CryptBuf>(16u); salt->rand(); size_t keyIter = 1024; CryptHmac secretKey(passphrase, salt->base64(), keyIter); printf("Salt %s keyIter %d\n", salt->base64().c_str(), keyIter); Glib::ustring plain = u8"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789öäüß"; Glib::ustring add = u8"name"; // ensures that a encryption for a different context may not be exchanged CryptMessage encrypt(plain, add, secretKey); auto iv = encrypt.getIV(); auto tag = encrypt.getTag(); auto encrypted = encrypt.getCipherText(); printf("Encrypted %s tag %s\n", encrypted->base64().c_str(), tag->base64().c_str()); CryptMessage decrypt(iv->base64(), encrypted->base64(), add, secretKey, tag->base64()); auto text = decrypt.getPlainText(); printf("Decrypted %s \n", text.c_str()); } catch (const CryptException& exc) { std::cout << "Exception " << exc.what() << std::endl; } }
Custom painting
package de.pfeifersyscon.charfill; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; import java.awt.Font; import java.awt.FontMetrics; import java.awt.GradientPaint; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Rectangle; import java.awt.RenderingHints; import java.awt.Shape; import java.awt.font.FontRenderContext; import java.awt.font.GlyphVector; import java.awt.geom.AffineTransform; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.SwingUtilities; /** * * @author rpf */ public class Charfill extends JFrame { public class Drawingarea extends JPanel { protected Drawingarea() { Dimension dim = new Dimension(640, 480); setPreferredSize(dim); setMinimumSize(dim); } public void paintComponent(Graphics g) { super.paintComponent(g); Graphics2D g2 = (Graphics2D)g; g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); Font font = Font.decode("serif-normal-48"); FontMetrics fontMetrics = getFontMetrics(font); String text = "Hello, World!"; int width = fontMetrics.stringWidth(text); int height = fontMetrics.getHeight(); FontRenderContext frc = fontMetrics.getFontRenderContext(); GlyphVector v = font.createGlyphVector(frc, text); Shape textShape = v.getOutline(); g2.transform(AffineTransform.getTranslateInstance(10.0, 20.0+height)); Shape rect = new Rectangle(0,0, width,height); GradientPaint paint = new GradientPaint(0,0,Color.RED,width, height,Color.GREEN); g2.setPaint(paint); g2.fill(textShape); //for (int i = 0; i < width+height; ++i) { // g2.setColor(i % 2 == 0 ? Color.GREEN : Color.RED); // g2.drawLine(i, 0, i-height, height); //} //g2.dispose(); } } private Drawingarea drawingarea; protected Charfill() { super("Charfill"); setDefaultCloseOperation(EXIT_ON_CLOSE); drawingarea = new Drawingarea(); add(drawingarea, BorderLayout.CENTER); pack(); } private static void initGui() { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { Charfill charfill = new Charfill(); charfill.setVisible(true); } }); } public static void main(String[] args) { initGui(); } }