Giter Site home page Giter Site logo

luke-park / securecompatibleencryptionexamples Goto Github PK

View Code? Open in Web Editor NEW
264.0 7.0 44.0 105 KB

A collection of secure encryption examples for encrypting strings and binary data.

License: MIT License

Go 3.32% Java 5.90% JavaScript 9.33% C# 5.85% PHP 2.29% Swift 5.92% Kotlin 4.79% Python 2.56% C 32.95% C++ 2.92% Objective-C 2.85% Ruby 2.80% Rust 6.26% TypeScript 3.37% Visual Basic .NET 6.26% Raku 2.62%
encryption best-practice example php csharp golang java javascript swift gcm

securecompatibleencryptionexamples's Introduction

Secure Compatible Encryption Examples

This repository was created to address the ever-growing number of poor encryption code examples that float about the internet. This repository will expand over time to include examples in more languages.

As of April 2021, there are 18 different compatible examples for 15 different languages across 5 different platforms.

Algorithms

  • Encryption: AES-128-GCM
  • Key Deriviation: PBKDF2
  • PBKDF2 Underlying Hash: SHA-256

AES with a 128-bit key was chosen due to the Java Unlimited Strength Policy that requires key sizes of no more than 128-bits due to cryptography export laws. While the examples are shown using AES-128, they can be trivially changed to 256-bit AES by changing the ALGORITHM_KEY_SIZE (and in some cases, ALGORITHM_NAME) parameter.

Compatibility

Every example shown here is compatible across platforms and/or languages. The result of encryptString in any language can be decrypted by decryptString in any language. Please do not submit pull requests for examples that are not compatible with the existing examples.

Methods

Each example exposes 4 methods with signatures that are roughly equivalent to the following:

  • string encryptString(plaintext: string, password: string)
  • string decryptString(ciphertext: string, password: string)
  • byte[] encrypt(plaintext: byte[], key: byte[])
  • byte[] decrypt(ciphertext: byte[], key: byte[])

As is expected, the encrypt and decrypt methods operate on and return raw binary data. The *string methods, however, take string parameters and return base64 encoded strings. The password parameter is fed through PBKDF2 first. password can be of any length but key must be 128-bits in length. You can change the AES key size by adjusting the ALGORITHM_KEY_SIZE parameter, and in some examples, the ALGORITHM_NAME parameter too.

NOTE: Because of the use of PBKDF2, the binary vs string methods are not compatible.

Dependencies

Language Version Tested Dependencies Notes
Java Java 8 JRE
Kotlin Java 8 JRE
JavaScript (Node) NodeJS 8.4.0 Tested on 8.4.0, but supported in versions as early as 4.0.0
JavaScript (Browser) Requires base64-js Uses the WebCrypto API, ensure browser support before using this example.
JavaScript (SJCL) Requires the Stanford JavaScript Crypto Library Doesn't run asynchronously.
Go Go 1.9 golang.org/x/crypto/pbkdf2 Tested on 1.9 but supported in earlier versions.
Python v3.6.4 Requires PyCryptodome No support for Python 2.
Ruby v2.4.4 Uses the OpenSSL Gem
Visual Basic .NET .NET 4.5 Requires BouncyCastle.
C# .NET 4.5 Requires BouncyCastle.
C Requires OpenSSL libssl-dev Uses SCEE.h header file.
C++ Requires C++11 Compiler Requires OpenSSL libssl-dev Wrapper for the C example. Requires SCEE.h and SCEE_cpp.h
Objective-C Requires OpenSSL libssl-dev Wrapper for the C example. Requires SCEE.h and SCEE_objc.h
Rust v1.30.0 Requires the ring v0.13.2 and base64 v0.9.3 crates
Swift Swift 4.0 Requires SwiftGCM. Must use a bridge for CommonCrypto.
PHP Requires PHP 7 Uses random_bytes which requires PHP 7.
Perl Perl 5 Requires CryptX

Test Vectors

The following ciphertexts are the results of encryptString using the given password. If your implementation can encryptString and decryptString using the code you've written, and can also decryptString the ciphertexts below to the same given result, then it is suitable for inclusion in this repository. Recall that, due to a randomly generated salt and nonce, the following are not expected outputs for encryptString, they are for testing decryptString only.

Ciphertext Password Plaintext
CqjxsXq6Y5ebtW6w98UQfgwdOpaCCkCy0l1qK5gJfhZnKVhp4+OuvxoiigHi8mO1R8CAyl5t DTY62mV2Cv XCbJbjd72q
VtHh3Z6jqJpIDK0yLe4+/UNpxqBqcmaiJWmaecb7qfCyOlAcVJ973zBNM51VCup5UTuVlu3H Pl4WODjq4k SOJHSCm4qR
SNQHdWnlcmJELLKewNTxBhzmJ1U+ChqKK5Kdvd/FSKssHW5b8y8SOrNVHdm78JUAYpGKlEUD BZO8PUEysY NYzd53moLT
5EmCwwSWj6YYgxBlld6DFW8I+QXCWxz5g/laEwUYV/DuoCGvxbW4ZlMd1Tsj4N07WbBOhIJU OziaxPFGYh vW1Qjb30mt
7miUNuhjJPAlbIHYKA2v/iBH3aplFF0pGw6HQAD5tKluh/1M69MLQ9xIkVcGfTr0CycsTFLU gkLDY5mmzT 9z19eFctoZ
0iqwbC8/1YvTsl2dog6aXaGfXVypsv1BcbnDE06C7nl9REITn3NW18+ZUmc= Empty String Empty String

C Example

The C example requires a bit more effort to understand and use properly due to varying buffer sizes with regard to base64 padding. The example below shows how to use crypt_string_get_length to determine what buffer size you will need to allocate to store the result.

#include "SCEE.h"
#include <stdio.h>

int main(int argc, char* argv[]) {

    // Our plaintext and password.
    unsigned char plaintext[] = "Hello, World!";
    unsigned char password[] = "OddShapelyOak7332";

    // Make enough space for our ciphertext.
    // Note that scee_crypt_string_get_length will give us the size of the buffer we
    // need INCLUDING the null character.
    size_t ct_length = scee_crypt_string_get_length(strlen(plaintext), SCEE_CRYPT_ENCRYPT);
    unsigned char ciphertext[ct_length];

    // Encryption.
    // The operation places the null character at the end of the buffer for us.
    int r = scee_encrypt_string(plaintext, strlen(plaintext), password, strlen(password), ciphertext);
    if (r != SCEE_OK) { return 1; }

    // Output for Encryption.
    printf("Ciphertext Buffer Size: %zu\n", ct_length);
    printf("Ciphertext strlen     : %zu\n", strlen(ciphertext));
    printf("Ciphertext            : %s\n\n", ciphertext);

    // Make enough space for our plaintext again.
    // Note that because of base64 padding, scee_crypt_string_get_length will
    // usually tell us that we need more space than we do.  We can get the
    // actual length of the plaintext after we decrypt.
    size_t pt_max_length = scee_crypt_string_get_length(strlen(ciphertext), SCEE_CRYPT_DECRYPT);
    size_t pt_actual_length;
    unsigned char plaintext2[pt_max_length];

    // Decryption.
    // The operation places the null character at the end of the buffer for us.
    r = scee_decrypt_string(ciphertext, strlen(ciphertext), password, strlen(password), plaintext2, &pt_actual_length);
    if (r != SCEE_OK) { return 1; }

    // Output for Decryption.
    printf("Plaintext Buffer Size: %zu\n", pt_max_length);
    printf("Plaintext Actual Size: %zu\n", pt_actual_length);
    printf("Plaintext strlen     : %zu\n", strlen(plaintext));
    printf("Plaintext            : %s\n\n", plaintext);

    return 0;
}

securecompatibleencryptionexamples's People

Contributors

alexendoo avatar codeweb avatar dblazeski avatar henry-gower-glenn avatar luke-park avatar onury avatar sherwind avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

securecompatibleencryptionexamples's Issues

OpenSSL example

It would be helpful for testing purposes to have bash OpenSSL/FreeSSL example with the same logic.

Java Unlimited Strength Policy is no longer a thing

Java Unlimited Strength Policy is no longer a thing and enabled by default. See

The current versions of JDK 8, 7, and 6 are 8u302, 7u312, and 6u119. It was always enabled on JDK 11 and 17.

Java code doesn't contain any exception handling

Please see my answer here to get an idea on how to handle those exceptions. Some definitely do not need to be handled by the user.

Note: I would try and make the iteration count configurable and include some kind of protocol description / version string.

Maximum ciphertext size?

What would be the technical size limitation for these examples. If the cipher (ArrayBuffer).

Does Reading, Encrypting & Decryption support streaming or chunking data?

I assume then you would need the same amount memory as per the cyphertext size.

i.e. 1gb of cipher text would mean you would need 2gb of memory ?

AES-256 Example

I use this mainly for Node.js.

I understand that AES with a 128-bit key was chosen due to the Java Unlimited Strength Policy that requires key sizes of no more than 128-bits due to cryptography export laws.

You said this can be trivially changed to 256-bit AES by changing the ALGORITHM_KEY_SIZE (and in some cases, ALGORITHM_NAME) parameter.

Could you provide a configuration for this that would work across platforms & languages. For example, would you say below would be performant and work across platforms:

const ALGORITHM_NAME = "aes-256-cbc";
const ALGORITHM_NONCE_SIZE = 12;
const ALGORITHM_TAG_SIZE = 16;
const ALGORITHM_KEY_SIZE = 32;
const PBKDF2_NAME = "sha256";
const PBKDF2_SALT_SIZE = 16;
const PBKDF2_ITERATIONS = 32767;

Note: This link (Oracle Java 8u162) indicates that Java cryptography is no longer restricted.

AES256GCM Decryption issue.

Hello there, I have been working on some encryption decryption thing. I'm unable to decrypt the Ciphertext .

Ciphertext: aqCZaIupuXS6N4LoJMc3XOsDdJYlpQNpitykLFN9UapdKMW8oK1HFLPar0B8GQ
Key: 78214125442A472D4B6150645367566B

Using this method to decrypt Ciphertext
let c2 = try SecureCompatibleEncryptionExamples.decryptString(ciphertext:"aqCZaIupuXS6N4LoJMc3XOsDdJYlpQNpitykLFN9UapdKMW8oK1HFLPar0B8GQ+lrYHvFbMk", password:"78214125442A472D4B6150645367566B")

Java code does not compile

The Java code does not compile because:

  • the name of the public type (SecureCompatibleEncryptionExamples) does not match the file name SCEE.java -> either rename the class to SCEE or rename the file to SecureCompatibleEncryptionExamples.java
  • the declared package scee does not match the source package -> either move SCEE.java to a scee subfoler or declare SecureCompatibleEncryptionExamples in the default package (this is not recommended).

Need help to convert java decrypt code to node JS code

@luke-park the below code is not an issue.can you please help to convert the below java code.
Followed your answer as like from stackoverflow
https://stackoverflow.com/questions/49021171/how-to-derive-iv-and-key-to-crypto-createcipheriv-for-decryption

      //Private Variables
        private Secretkeyfactory secretkeyfactory ;
        private Cipher cipher;

        //Constructor
        public Decrypt128CBC()
        {
          this.secretkeyfactory =Secretkeyfactory.getInstance("PBKDF2WithHmacSHA1");
          this.cipher=Cipher.getInstance("AES/CBC/PKCS5Padding")
        }
            Public string DecryptedValue(String Ecryptedbase64string,String secKey)
            {
             byte[] dcdbytes=Base64.decodeBase64(Ecryptedbase64string.getBytes());
            byte[] calculatesalt=Arrays.copyOfRange(dcdbytes,0,32);
            byte[] initialvecto=Arrays.copyOfRange(dcdbytes,32,48);
            byte[] encodedtext=Arrays.copyOfRange(dcdbytes,48,dcdbytes.length);
            SecretKey sk=getRandompwd(calculatesalt,secKey);
            IvParameterSpec vectspec=new IvParameterSpec(initialvecto);
            byte[] decrtptxt=null;
            synchronized(cipher){
            cipher.init(Cipher.DECRYPT_MODE,sk,vectspec);
            decrtptxt=cipher.doFinal(encodedtext)
            }
        String finalvalue=new String(decrtptxt);
        return finalvalue;
            }
        
        private SecretKey getRandompwd(byte[] salt,String secKey)
        {
        SecretKeySpec objSecKeySpec=new SecretKeySpec(Base64.decodeBase64(secKey),"HmacSHA1");    
        String skey=Base64.encodeBase64String(objSecKeySpec.getEncoded());
        KeySpec kspec=new PBEKeySpec(skey.toCharArray(),salt,76456,128);
        SecretKey tmpSecKey=secretKeyKactory.generateSecret(kspec);
        byte[] encoded=tmpSecKey.getEncoded();
        return new SecretKeySpec(encoded,'AES')
        }

Here is the node JS code I tried. I tried lots of option with crypto but not able to. My final output is coming with some junk characters like square,symbols etc...

var crypto=require('crypto');

var Ecryptedbase64string='fsffsfgf6575FGHDM767fsffsfs...…...';
var DecryptKey='J8nMD7ZnFg......';

var byteEncryptedString=new Buffer(Ecryptedbase64string,'base64');
var binaryKey=new Buffer(DecryptKey,""base64);
var salt=byteEncryptedString.slice(0,32);
var iv=byteEncryptedString.slice(32,48);
var cipherText=byteEncryptedString.slice(48,byteEncryptedString.length);


var callback=function(err,key){
let cipher=crypto.createDecipheriv('AES-128-CBC',key,iv);
let finalDecrptedText=Buffer.concat([cipher.update(cipherText),cipher.final()]);
};

crypto.pbkdf2(binaryKey,salt,76456,16,callback);

authTagValidation error Swift

I've imported the Swift example and run it on one of the ciphertexts from the README file. The decrypt function always returns authTagValidation error.

I'm using Swift 5, imported SwiftGCM and CommonCrypto.

Example test code:

func testSjclEncrypt() {
       let test = "5EmCwwSWj6YYgxBlld6DFW8I+QXCWxz5g/laEwUYV/DuoCGvxbW4ZlMd1Tsj4N07WbBOhIJU"
        do  {
            let decrypted = try AES256.decryptString(ciphertext: test, password: "OziaxPFGYh")
            print("decrypted: \(decrypted)")
        } catch (let error) {
            print("this is error: \(error)")
        }
    }

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.