Giter VIP home page Giter VIP logo

easyrsa's People

Contributors

codermarcel avatar lsmith77 avatar paragonie-scott avatar paragonie-security 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  avatar  avatar  avatar  avatar  avatar

easyrsa's Issues

RSA encryption doesn't actually use RSAES-OAEP + MGF1+SHA256(?)

I wrote a Java library compatible with EasyRSA. It is working but I had to change the code of the function getRsa (line 39 in EasyRSA.php) - I added the following lines:
after line 44: $rsa->setHash('sha256');
after line 47: $rsa->setEncryptionMode($mode);

Before adding those lines, I wasn't able to decrypt the RSA part with Java, but after adding them I could decrypt the RSA part with algorithm "RSA/ECB/OAEPWithSHA-256AndMGF1Padding".

So, my question is: Is the code in EasyRSA.php wrong or is it supposed to be different from Java algorithm "RSA/ECB/OAEPWithSHA-256AndMGF1Padding"?

Support private key encryption, public key decryption

I have a scenario whereby I want an actor to encrypt a message with a private key, and anyone with the public key can decrypt the message.

Currently this library only supports public key encryption and private key decryption.

[ISSUE] Decryption failed with Message encrypted by Public Key generated by Mailvelope

Hi,

I tried to encrypt content with RSA/4096 key generated by Mailvelope, then the web server send the encrypted message to my email, in order to use Mailvelope to decrypt and read server message from my mail box directly without copy and paste everytime.
But, it fails to be decypted by Mailvelope look here:

Error message:

screenshot from 2018-07-02 11-56-05

I even tried to add a header and footer for the encrypted message like this:

-----BEGIN PGP MESSAGE-----
EzR2$$3vUCAOMixWpGR7SRCF8w6WF3I4EwmFTmy4tytt+dmakTHeMadtkuJnWSEMeq5uM6hGy/dUEyZY/3oqcGC+ZqYFNlSjumeXDamrpZWgCiBrj1j2mCLIJ5Y3p7iA0ad1c=$d7a8998ed2d71e1d
-----END PGP MESSAGE-----

And error message changed to something else, look here:

screenshot from 2018-07-02 11-54-51

I add a new line after header line, like this:

-----BEGIN PGP MESSAGE-----

EzR2$$3vUCAOMixWpGR7SRCF8w6WF3I4EwmFTmy4tytt+dmakTHeMadtkuJnWSEMeq5uM6hGy/dUEyZY/3oqcGC+ZqYFNlSjumeXDamrpZWgCiBrj1j2mCLIJ5Y3p7iA0ad1c=$d7a8998ed2d71e1d
-----END PGP MESSAGE-----

And error message changed again, look here:

screenshot from 2018-07-02 12-08-28

Snippet to generate encrypted message:

$message = "Hello World";
$public = new ParagonIE\EasyRSA\PublicKey(file_get_contents("keys/Debugging_pub.asc"));
$cipher_message = ParagonIE\EasyRSA\EasyRSA::encrypt($message, $public);

keys/Debugging_pub.asc

-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: Mailvelope v2.2.2
Comment: https://www.mailvelope.com

xsFNBFs533ABEACzNdFO7J5VDmrCz8XP9j2CmCasBCM8rOU+OcXIn/zkch9f
5dE/wy0dC7antytGax6lc6dQTdiu7u0vqIz5iML6LHtpV61kUSdyM3QpU+DZ
xRtA8+p6w6AzDk4DapQaybvT2jAFNEfJ3nEXAU8UVAcIhStozASW8a+KEvTA
RNGjWHbnQooUc1SEqGGlqRaPhxuIVJwEmD8tC6n8OlhR1vJcNg6Jx7GjTA8E
8ovsRacCYwpfYmtIObQrV84DcvUlcj6h4X7X3nfdkN8FhLIdCk9Ue4vwDGBb
wkR8oPr6Lx97gQNaUcqbN81xx5agi+Byq6OHzetfoD324vs/qq+5wCh3fz6n
aZTZ3xJq0Gjtkg+OdONFW2+EdxxWzq/FQML7JY8md44wu6gYEZwo+pA791Qn
mJwld5Bjz++Fwb/cd6YB7c6Lmslay8gHOJ92USMwPp+BIhNwZhF2CiXd9FMJ
zi53rWpa1GEblrZ154GADOPENMOwkcPJkk3GuH8/SUpfcQxNRgwoY8qPKZfF
yeStUXeCymCdHHe/EJCvtML0pM6guy0bPVe0s9kWYok2ctXjXKOukWqDCrg5
9jiociN2VUJgIFxxtP+4aEEtMslcpBgsA2eEOr832AFVnkWNENYkNrRUuyIu
kNxlHVqAat8SdfUseb/6E3kkDE2j4ivV2uniSQARAQABzSpLYWZlaCBEZWJ1
Z2dpbmcgPGthZmVoLmphemFuLnNhQGdtYWlsLmNvbT7CwXUEEAEIACkFAls5
33MGCwkHCAMCCRAXs80E1089fAQVCAoCAxYCAQIZAQIbAwIeAQAAnXQP/jXq
L273nMFfskQWp5cuH6PVzU8+CW8320rfia3oF0z/D2Dh8AhUnCrm7ndqGS+t
hASugkIDnGdAhMCBZhDEZubNUnf91s2rKYu9Yaj2Tha+0syx7AxbfG/XRm/e
XhNWLBts5axh+fg8IVvqfSAQfSU0hupB8iIXR+rdBpYNxibtHWjN1go97PcH
cHAbgjoJvjWKImhugVBvkJedwYENx1oqQJtRel4rnsZ38h++TIvMtGXHlG5n
8zDXtY02wpp42LO4L21SK4YOhLN8swWCImlg2fR4Yazh49/I+nhmCbbJsdEr
e2vlBJOWQy/8qq/al7A90SsxlJIMOpVi+/+n/t2iIwQxGvzlkZKr1EbKPQqH
diGcQoi+ynPstx7gcHQBSWloZdRgsliWeUwvrgvDxVDl80KWLxKaH1Yf0JZz
dMcbtFCAbKzBbce/v2U7CChd/DtjFlANSbWwYDAjMuuzh8UwskbQM0hjVmmW
gf+j3vO0v3dav7atq9KxSn76sjnsEUQqcvYRedY1aj7XxCWKTfW6HPtJmnHs
k3VIhA4o/OP7Ya5lGicpeRYFv/ZewISsVIRQ1VGramiylbDhQ7b0a91UdDOB
I3wtBjnn7zid7TOu4uiv6Ku66SO+RoS+Sau+WzISoaYhVm1ZR63p8zYxqlzz
KDO7vK8p6Dg6yBTu7Uq/zsFNBFs533ABEACQK2I5iRI9HLioq9whBQRx2sQQ
Vi6Djw27r1VD72Y1G7aUe24iFg2wrXlloMUNB5iIKB1vXy6cnRll570LVkUZ
UfUdH4nN8kz7UrHXAfzA6YQtb2TRHRmE89WgFJF2N40LKxDC1jc86sh4ufOl
aR8YAIAwO/WS9DedbV0U9otEHDwCaWy0n5K17cS91Ug+7ykSpliGeiqRcwT3
cXFOmtWM7IywKCym9sVsJHqxx1iyoNhiM9rLLEZw/RJmBAfOJFjgK91/HBlv
fanpMnhoNZpd9vODhXer+pLk7iv1O9VpvDqIgEH0lITnYu3FO9TXbhpKmxtX
Iocgrb3rvCKKKUm8QNMbLKkp/lkLrPkJ8E9pGgb8KvFCA2z1157iRto3C2Et
T2ndwB23OnntUVbJPJGTfC7CltjU/y3EXLiLCICOI6xtrfT0uPs8KnD47uuP
0hWjKUPQJN6oqsCeBiqkPhFGwLX6GVnQLlAXrnOq5qWirLRngMXDbZeNafYI
X/fUY6uE0SSvLN0ExVk3sqKYh0m4Rnxn2U6V4mV00k+AFoVYCP+MlYrp8+PG
a+ej7Rk7m/kl8HOW5iMLa3OclGbQYymz0mEgAA779Ddw6faA2lvT7JTWATRH
VD8BL7/07IlNC5GOqulyGpgPXBcfPxHLsYa15DYDT8sa0aUZR22cn6V3GwAR
AQABwsFfBBgBCAATBQJbOd90CRAXs80E1089fAIbDAAAgiEQAISu1t63Nn8J
kt8UzheLz3FVkZ0qWJl8grXkzjLjn5knBV/Alblk16pb/MvX/uw6yCHdsB+h
rUjXEi+n7GD0Jv/3Aia1E2/zWeU0NCqvtlvb8i8Mm0Kw72OPoeZZDAPldvKR
Zxsdth69xLuLSqiOd1RSuQ+7d+ZL9kQZq6nZU/p4aBLBYdNHz7u27aRn3GLe
UimZImPByZTaoUaSn8nxXCmsT4OKpymYU8ZmaDI2e9aLJ+oHVwurDyHVwmfX
4T/XJEMrXktp3IPdST87qf/2TPcMR1z2qyr7h/a5jbN8ojFQFv9t7+IgF3BZ
EdT4HPok/OFZFQ1N7vyzMoJgP3UC6MYTx9gX3msF1j4Do19gSxYgki7rKyyT
4PAyHqc/Y1TgpV7uI4NdfatL0t8UBOFfA9KKchA8XxTvDmS8PVV37bUtRJhN
TV0jgHhjjNFGcwyffl7z08qfucWK82/Qm+QMBHYyavvYYDAj7WIOggrEtoje
OgqdwCEyNMLa3j8Sb6mArj69+C/qjanrc1mPtJK/KaKc1xga3UoN3r0eB3Sw
ybaMcqIMXd1tJrizYciDjEfyeSl/Ba7qx80nmwLpJBEr3TWC0iOmJwcmdBAl
ncE0gDOANoSewIZJvovi1xmixWmTyDCR4QgdpLVrq1XtLrY+h8OTtmVk8LJ4
kIh7Gdrpglua
=mpfx
-----END PGP PUBLIC KEY BLOCK-----

As I think the library itself didn't complaint about the public key and the encryption process just done fine.

What I missed here, could anyone help me out?

Thanks

Rethink strategy

OAEP may be totally bogus. The security proof sure is.

Instead of:

  1. Generate random key $k
  2. Encrypt message with $k, using authenticated encryption.
  3. Encrypt $k with RSA public key.

We should:

  1. Generate a random message, $m.
  2. Encrypt random message using RSA, producing $c.
  3. Use hash_hmac('sha256', $m, $c) as $k for encrypting the actual message.
  4. Send $c, and the encrypted message. Only the recipient can recover $m to generate $k and decrypt.

Help to translate javascript encoding to php

Hello!

I'm trying to translate this script to php without success for a few days... maybe you could help me a little bit

(function (window) {
    var Juno = window.Juno || {};
    window.Juno = Juno;

    function Card() {
        var self = this;
        this.mask = {
            DEFAULT_CC: '0000  0000  0000  0000',
            DEFAULT_CVC: '000',
        }
        this.type = {
            VISA: {
                name: 'visa',
                detector: /^4/,
                cardLength: 16,
                cvcLength: 3,
                maskCC: self.mask.DEFAULT_CC,
                maskCVC: self.mask.DEFAULT_CVC,
                order: 99
            },
            MASTERCARD: {
                name: 'mastercard',
                detector: /^(5[1-5]|2(2(2[1-9]|[3-9])|[3-6]|7([0-1]|20)))/,
                cardLength: 16,
                cvcLength: 3,
                maskCC: self.mask.DEFAULT_CC,
                maskCVC: self.mask.DEFAULT_CVC,
                order: 99
            },
            AMEX: {
                name: 'amex',
                detector: /^3[47]/,
                cardLength: 15,
                cvcLength: 4,
                maskCC: '0000  000000  00000',
                maskCVC: '0000',
                order: 99
            },
            DISCOVER: {
                name: 'discover',
                detector: /^6(?:011\d{12}|5\d{14}|4[4-9]\d{13}|22(?:1(?:2[6-9]|[3-9]\d)|[2-8]\d{2}|9(?:[01]\d|2[0-5]))\d{10})/,
                cardLength: 16,
                cvcLength: 3,
                maskCC: self.mask.DEFAULT_CC,
                maskCVC: self.mask.DEFAULT_CVC,
                order: 2
            },
            HIPERCARD: {
                name: 'hipercard',
                detector: /^606282|384100|384140|384160/,
                cardLength: 16,
                cvcLength: 3,
                maskCC: self.mask.DEFAULT_CC,
                maskCVC: self.mask.DEFAULT_CVC,
                order: 4
            },
            DINERS: {
                name: 'diners',
                detector: /^(300|301|302|303|304|305|36|38)/,
                cardLength: 14,
                cvcLength: 3,
                maskCC: '0000  000000  0000',
                maskCVC: self.mask.DEFAULT_CVC,
                order: 5
            },
            JCB_15: {
                name: 'jcb_15',
                detector: /^2131|1800/,
                cardLength: 15,
                cvcLength: 3,
                maskCC: self.mask.DEFAULT_CC,
                maskCVC: self.mask.DEFAULT_CVC,
                order: 6
            },
            JCB_16: {
                name: 'jcb_16',
                detector: /^35(?:2[89]|[3-8]\d)/,
                cardLength: 16,
                cvcLength: 3,
                maskCC: self.mask.DEFAULT_CC,
                maskCVC: self.mask.DEFAULT_CVC,
                order: 7
            },
            ELO: {
                name: 'elo',
                detector: /^(4011(78|79)|43(1274|8935)|45(1416|7393|763(1|2))|50(4175|6699|67([0-6][0-9]|7[0-8])|9\d{3})|627780|63(6297|6368)|650(03([^4])|04([0-9])|05(0|1)|4(0[5-9]|(1|2|3)[0-9]|8[5-9]|9[0-9])|5((3|9)[0-8]|4[1-9]|([0-2]|[5-8])\d)|7(0\d|1[0-8]|2[0-7])|9(0[1-9]|[1-6][0-9]|7[0-8]))|6516(5[2-9]|[6-7]\d)|6550(2[1-9]|5[0-8]|(0|1|3|4)\d))\d*/,
                cardLength: 16,
                cvcLength: 3,
                maskCC: self.mask.DEFAULT_CC,
                maskCVC: self.mask.DEFAULT_CVC,
                order: 1
            },
            AURA: {
                name: 'aura',
                detector: /^((?!5066|5067|50900|504175|506699)50)/,
                cardLength: 19,
                cvcLength: 3,
                maskCC: '0000000000000000000',
                maskCVC: self.mask.DEFAULT_CVC,
                order: 3
            }
        };
    }
    Card.prototype = {
        getType: function (value) {
            var cardNo = value.replace(/ /g, '');
            for (var key in this.getOrderedTypes()) {
                if (this.validator.number(cardNo, this.type[key])) {
                    return this.type[key];
                }
            }
            return false;
        },
        getOrderedTypes: function () {
            var types = {};
            var order = 1;
            while (order < 100) {
                for (var key in this.type) {
                    if (this.type[key].order == order) {
                        types[key] = this.type[key];
                    }
                }
                order++;
            }
            return types;
        },
        validateNumber: function (value) {
            var cardNo = value.replace(/ /g, '');
            var type = this.getType(cardNo);
            return type && type.cardLength == cardNo.length && this.validator.luhn(cardNo);
        },
        validateCvc: function (cardNo, cvcNo) {
            cardNo = cardNo.replace(/ /g, '');
            var type = this.getType(cardNo);
            return type && this.validator.cvc(cvcNo, type);
        },
        validateExpireDate: function (expirationMonth, expirationYear) {
            var today = new Date();
            var month = today.getMonth() + 1;
            var year = today.getFullYear();
            expirationMonth = parseInt(expirationMonth);
            expirationYear = parseInt(expirationYear);
            if (expirationMonth > 0 && expirationYear > 0 && expirationYear >= year) {
                if (expirationYear == year) {
                    return (expirationMonth > month);
                }
                return true;
            }
            return false;
        },
        validator: {
            number: function (cardNo, type) {
                return type.detector.test(cardNo);
            },
            luhn: function (cardNo) {
                var numberProduct, checkSumTotal = 0;
                for (var digitCounter = cardNo.length - 1; digitCounter >= 0; digitCounter = digitCounter - 2) {
                    checkSumTotal += parseInt(cardNo.charAt(digitCounter), 10);
                    numberProduct = String((cardNo.charAt(digitCounter - 1) * 2));
                    for (var productDigitCounter = 0; productDigitCounter < numberProduct.length; productDigitCounter++) {
                        checkSumTotal += parseInt(numberProduct.charAt(productDigitCounter), 10);
                    }
                }
                return (checkSumTotal % 10 == 0);
            },
            cvc: function (cvcNo, type) {
                return type.cvcLength == ('' + cvcNo).length;
            }
        }
    };
    Juno.Card = Card;
})(window);

(function (window) {
    var Juno = window.Juno || {};
    window.Juno = Juno;
    if ("undefined" === typeof TextEncoder) {
        TextEncoder = function () {};
        TextEncoder.prototype.encode = function (e) {
            for (var f = e.length, b = -1, a = "undefined" === typeof Uint8Array ? Array(1.5 * f) : new Uint8Array(3 * f), c, g, d = 0; d !== f;) {
                c = e.charCodeAt(d);
                d += 1;
                if (55296 <= c && 56319 >= c) {
                    if (d === f) {
                        a[b += 1] = 239;
                        a[b += 1] = 191;
                        a[b += 1] = 189;
                        break;
                    }
                    g = e.charCodeAt(d);
                    if (56320 <= g && 57343 >= g) {
                        if (c = 1024 * (c - 55296) + g - 56320 + 65536, d += 1, 65535 < c) {
                            a[b += 1] = 240 | c >>> 18;
                            a[b += 1] = 128 | c >>> 12 & 63;
                            a[b += 1] = 128 | c >>> 6 & 63;
                            a[b += 1] = 128 | c & 63;
                            continue;
                        }
                    } else {
                        a[b += 1] = 239;
                        a[b += 1] = 191;
                        a[b += 1] = 189;
                        continue;
                    }
                }
                127 >= c ? a[b += 1] = 0 | c : (2047 >= c ? a[b += 1] = 192 | c >>> 6 : (a[b += 1] = 224 | c >>> 12, a[b += 1] = 128 | c >>> 6 & 63), a[b += 1] = 128 | c & 63);
            }
            if ("undefined" !== typeof Uint8Array) {
                return a.subarray(0, b + 1);
            }
            a.length = b + 1;
            return a;
        };
        TextEncoder.prototype.toString = function () {
            return "[object TextEncoder]";
        };
        try {
            Object.defineProperty(TextEncoder.prototype, "encoding", {
                get: function () {
                    if (TextEncoder.prototype.isPrototypeOf(this)) {
                        return "utf-8";
                    }
                    throw TypeError("Illegal invocation");
                }
            });
        } catch (e) {
            TextEncoder.prototype.encoding = "utf-8";
        }
        "undefined" !== typeof Symbol && (TextEncoder.prototype[Symbol.toStringTag] = "TextEncoder");
    }

    function Crypto() {
        this.chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
        this.lookup = new Uint8Array(256);
        this.initB64();
    }
    Crypto.prototype = {
        encrypt: function (pemPublicKey, stringData) {
            return this.importPublicKey(pemPublicKey).then(function (publicKey) {
                return new Promise(function (resolve, reject) {
                    var data = this.stringToArrayBuffer(stringData);
                    console.log({
                        data
                    });
                    window.crypto.subtle.encrypt({
                        name: "RSA-OAEP",
                        hash: {
                            name: "SHA-256"
                        }
                    }, publicKey, data).then(function (encrypted) {
                        var encoded = this.encodeAb(encrypted);
                        resolve(encoded);
                    }.bind(this)).catch(function (err) {
                        reject(err);
                    });
                }.bind(this));
            }.bind(this));
        },
        importPublicKey: function (pemPublicKey) {
            return new Promise(function (resolve, reject) {
                window.crypto.subtle.importKey("spki", this.pemToArrayBuffer(pemPublicKey), {
                    name: "RSA-OAEP",
                    hash: {
                        name: "SHA-256"
                    }
                }, false, ["encrypt"]).then(function (importedKey) {
                    resolve(importedKey);
                }).catch(function (err) {
                    reject(err);
                });
            }.bind(this));
        },
        initB64: function () {
            for (var i = 0; i < this.chars.length; i++) {
                this.lookup[this.chars.charCodeAt(i)] = i;
            }
        },
        removeLines: function (str) {
            return str.replace("\n", "");
        },
        base64ToArrayBuffer: function (b64) {
            var byteString = window.atob(b64);
            var byteArray = new Uint8Array(byteString.length);
            for (var i = 0; i < byteString.length; i++) {
                byteArray[i] = byteString.charCodeAt(i);
            }
            return byteArray;
        },
        pemToArrayBuffer: function (pem) {
            var b64Lines = this.removeLines(pem);
            var b64Prefix = b64Lines.replace('-----BEGIN PUBLIC KEY-----', '');
            var b64Final = b64Prefix.replace('-----END PUBLIC KEY-----', '');
            return this.base64ToArrayBuffer(b64Final);
        },
        stringToArrayBuffer: function (str) {
            var encoder = new TextEncoder('utf-8');
            var byteArray = encoder.encode(str);
            return byteArray.buffer;
        },
        encodeAb: function (arrayBuffer) {
            var bytes = new Uint8Array(arrayBuffer),
                i, len = bytes.length,
                base64 = '';
            for (i = 0; i < len; i += 3) {
                base64 += this.chars[bytes[i] >> 2];
                base64 += this.chars[((bytes[i] & 3) << 4) | (bytes[i + 1] >> 4)];
                base64 += this.chars[((bytes[i + 1] & 15) << 2) | (bytes[i + 2] >> 6)];
                base64 += this.chars[bytes[i + 2] & 63];
            }
            if ((len % 3) === 2) {
                base64 = base64.substring(0, base64.length - 1) + '=';
            } else if (len % 3 === 1) {
                base64 = base64.substring(0, base64.length - 2) + '==';
            }
            return base64;
        }
    };
    Juno.Crypto = Crypto;
})(window);

(function (window) {
    var Juno = window.Juno || {};
    window.Juno = Juno;

    function DirectCheckout(publicToken, prod = true) {
        this._version = "0.0.2";
        this._url = 'https://' + (prod ? 'www' : 'sandbox') + '.boletobancario.com/boletofacil/integration/api/';
        this._publicKey = null;
        this._countAwaitingPublicKey = 0;
        this._publicToken = publicToken;
        this._crypto = new Juno.Crypto();
        this._card = new Juno.Card();
        this._loadPublicKey();
    }
    DirectCheckout.prototype = {
        getCardType: function (cardNumber) {
            return (this.isValidCardNumber(cardNumber)) ? this._card.getType(cardNumber).name : false;
        },
        isValidCardNumber: function (cardNumber) {
            return this._card.validateNumber(cardNumber);
        },
        isValidSecurityCode: function (cardNumber, securityCode) {
            return this._card.validateCvc(cardNumber, securityCode);
        },
        isValidExpireDate: function (expirationMonth, expirationYear) {
            return this._card.validateExpireDate(expirationMonth, expirationYear);
        },
        isValidCardData: function (cardData, error) {
            if (!this._publicKey) {
                error(Error('Invalid public key'));
                return false;
            }
            if (!cardData) {
                error(Error('Invalid card data'));
                return false;
            }
            if (!cardData.holderName || cardData.holderName == "") {
                error(Error('Invalid holder name'));
                return false;
            }
            if (!this.isValidCardNumber(cardData.cardNumber)) {
                error(Error('Invalid card number'));
                return false;
            }
            if (!this.isValidSecurityCode(cardData.cardNumber, cardData.securityCode)) {
                error(Error('Invalid security code'));
                return false;
            }
            if (!this.isValidExpireDate(cardData.expirationMonth, cardData.expirationYear)) {
                error(Error('Invalid expire date'));
                return false;
            }
            return true;
        },
        getCardHash: function (cardData, success, error) {
            this._checkPublicKey(function () {
                if (this.isValidCardData(cardData, error)) {
                    this._internalGetCardHash(cardData).then(function (cardHash) {
                        success(cardHash);
                    }, function (e) {
                        error(e);
                    });
                }
            }.bind(this));
        },
        _internalGetCardHash: function (cardData) {
            return new Promise(function (resolve, reject) {
                cardData = JSON.stringify(cardData);
                console.log({
                    cardData
                });
                this._crypto.encrypt(this._publicKey, cardData).then(function (encoded) {
                    var url = this._url + 'get-credit-card-hash.json';
                    var params = 'publicToken=' + this._publicToken;
                    params += '&encryptedData=' + window.encodeURIComponent(encoded);
                    this._ajax('POST', url, params).then(function (response) {
                        response = JSON.parse(response)
                        if (response.success) {
                            resolve(response.data);
                        } else {
                            reject(Error(response.errorMessage));
                        }
                    }.bind(this), function (error) {
                        reject(Error('Error on retrieve public key: ' + error));
                    });
                }.bind(this), function (error) {
                    reject(Error('Error on encrypt data: ' + error));
                });
            }.bind(this));
        },
        _loadPublicKey: function () {
            var url = this._url + 'get-public-encryption-key.json';
            var params = 'publicToken=' + this._publicToken + '&version=' + this._version;;
            this._ajax('POST', url, params).then(function (response) {
                response = JSON.parse(response);
                if (response.success) {
                    this._publicKey = response.data;
                } else {
                    throw Error(response.errorMessage);
                }
            }.bind(this), function (error) {
                throw Error("Error on retrieve public key", error);
            });
        },
        _ajax: function (type, url, params) {
            return new Promise(function (resolve, reject) {
                var req = new XMLHttpRequest();
                req.open(type, url);
                req.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
                req.onload = function () {
                    if (req.status == 200) {
                        resolve(req.response);
                    } else {
                        reject(Error(req.statusText));
                    }
                };
                req.onerror = function () {
                    reject(Error('Network Error'));
                };
                req.send(params);
            });
        },
        _checkPublicKey: function (callback) {
            if (!this._publicKey && this._countAwaitingPublicKey < 100) {
                setTimeout(function () {
                    this._countAwaitingPublicKey++;
                    this._checkPublicKey(callback);
                }.bind(this), 100);
            } else {
                callback();
            }
        }
    };
    window.DirectCheckout = DirectCheckout;
})(window);

This project has been created trying to figure out this https://github.com/carlosartur/junoCreditCardEncript

README: Specify handling of symmetric key in "Under the Hood".

Since you obviously aren't just sending the used symmetric key along unecrypted, there is a step or two in the "Under the Hood" part of the README that is missing to describe it being encrypted again using the public key (I imagine). Not many folks will need that info, but you do have an "Under the Hood" section, and it should be complete.

Ephemeral key should be "Symmetric key agreement key"

Hi there guys,

Lately we started using your library for some convenience methods for storing encrypted data.
Great work!

To the point. In the encrypt/decrypt method you name the generated key as ephemeral which is incorrect according to key cryptography, as far as I know, and should be named: "Symmetric key agreement key" according to wiki

Export public key

Ok, everything works well.
but how i can export the public key for an app?

$keyPair->getPublicKey();
is a protected object and his serialized version is too messy.

it will be nice if in the object will be implemented an export function like:

$objKey = $keyPair->getPublicKey();
return $objKey->export();

thanks

Rebrand Library?

EasyRSA is the name of another popular project. We should think of something better to call this.

Noob Question - Why create ephemeral key and symmetrically encrypt?

Hi there,

Great work on this repo. Though for my understanding I would like to know why, since you have a KeyPair, do you need to go into creating ephemeral keys add symmetric encryption and complicate this?

Would it not suffice just to use RSA() and the keyPair to handle encryption and decryption ?

I am asking this because the decision to support this packaged ephemeral key only brings problems for example the php-encryption incopatible upgrade and beats it's purpose since you don't reuse the ephemeral key (for multiple KEK).

Am I missing something here?

EasyRSA creates .rnd file in website root

Whenever I run the following code, everything will work as planned, but a .rnd file is created in my /public folder. I use this secure wrapper in combination with the laravel framework. Is there a way to alter the folder where this file is created or disable the creation? For clients will be able to download the .rnd file when they enter the adres /.rnd

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use ParagonIE\EasyRSA\KeyPair;
use ParagonIE\EasyRSA\EasyRSA;

class Rsacontroller extends Controller
{
    public function generateKeyPair()
    {
        $keyPair = KeyPair::generateKeyPair(4096);

        $secretKey = $keyPair->getPrivateKey();
        $publicKey = $keyPair->getPublicKey();

        var_dump($secretKey->getKey());
        echo "<br><br><br><br>";
        var_dump($publicKey->getKey());

        $message = "test";

        $ciphertext = EasyRSA::encrypt($message, $publicKey);

        $plaintext = EasyRSA::decrypt($ciphertext, $secretKey);

        echo "<br><br><br><br><br>";

        echo $ciphertext;

        echo "<br><br><br><br>";

        echo $plaintext;
    }
}

Remove phpseclib dependency

  • Implement RSAES-OAEP with MGF1-SHA256 and e = 65537 using only PHP and ext/openssl
  • Implement RSASSA-PSS with MGF1-SHA256 and e = 65537 using only PHP and ext/openssl
  • Ensure compatibility with phpseclib
  • Remove dependency from composer.json

Discussion: the purpose of a checksum

In the \ParagonIE\EasyRSA\EasyRSA::encrypt you're calculating a checksum as

        $checksum = \substr(
            \hash('sha256', $packaged),
            0,
            16
        );

What is the purpose for that? Especially that it does not contain any secret part.

Is it simply against data corruption? Just to avoid even trying to decrypt it when data was corrupted during transmission?

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.