diff --git a/GeneXusCryptography/src/main/java/com/genexus/cryptography/asymmetric/AsymmetricSigner.java b/GeneXusCryptography/src/main/java/com/genexus/cryptography/asymmetric/AsymmetricSigner.java index ec990fd..b154adb 100644 --- a/GeneXusCryptography/src/main/java/com/genexus/cryptography/asymmetric/AsymmetricSigner.java +++ b/GeneXusCryptography/src/main/java/com/genexus/cryptography/asymmetric/AsymmetricSigner.java @@ -32,25 +32,15 @@ public AsymmetricSigner() { @Override public String doSign(PrivateKeyManager key, String hashAlgorithm, String plainText) { - /******** INPUT VERIFICATION - BEGIN ********/ - if(key == null) - { - error.setError("AE001", "Private key cannot be null"); - return ""; - } - if(hashAlgorithm == null || hashAlgorithm.length() == 0 || SecurityUtils.compareStrings("", hashAlgorithm)) - { - error.setError("AE002", "HashAlgorithm cannot be empty value; use HashAlgorithm domain"); - return ""; - } - if(plainText == null || plainText.length() == 0 || SecurityUtils.compareStrings("", plainText)) - { - error.setError("AE003", "The plainText value to sign cannot be empty"); - return ""; - } - /******** INPUT VERIFICATION - END ********/ - + this.error.cleanError(); + /*******INPUT VERIFICATION - BEGIN*******/ + SecurityUtils.validateObjectInput("key", key, this.error); + SecurityUtils.validateStringInput("hashAlgorithm", hashAlgorithm, this.error); + SecurityUtils.validateStringInput("plainText", plainText, this.error); + if(this.hasError()) { return "";}; + /*******INPUT VERIFICATION - END*******/ + EncodingUtil eu = new EncodingUtil(); byte[] inputText = eu.getBytes(plainText); if (eu.hasError()) { @@ -63,30 +53,21 @@ public String doSign(PrivateKeyManager key, String hashAlgorithm, String plainTe result = sign(key, hashAlgorithm, inputStream); }catch(Exception e) { - error.setError("AE004", e.getMessage()); + error.setError("AS001", e.getMessage()); } return result; } @Override public String doSignFile(PrivateKeyManager key, String hashAlgorithm, String path) { - /******** INPUT VERIFICATION - BEGIN ********/ - if(key == null) - { - error.setError("AE005", "Private key cannot be null"); - return ""; - } - if(hashAlgorithm == null || hashAlgorithm.length() == 0 || SecurityUtils.compareStrings("", hashAlgorithm)) - { - error.setError("AE006", "HashAlgorithm cannot be empty value; use HashAlgorithm domain"); - return ""; - } - if(path == null || path.length() == 0 || SecurityUtils.compareStrings("", path)) - { - error.setError("AE007", "The path value of the file to sign cannot be empty"); - return ""; - } - /******** INPUT VERIFICATION - END ********/ + this.error.cleanError(); + + /*******INPUT VERIFICATION - BEGIN*******/ + SecurityUtils.validateObjectInput("key", key, this.error); + SecurityUtils.validateStringInput("hashAlgorithm", hashAlgorithm, this.error); + SecurityUtils.validateStringInput("path", path, this.error); + if(this.hasError()) { return "";} + /*******INPUT VERIFICATION - END*******/ String result = ""; try(InputStream input = SecurityUtils.getFileStream(path, this.error)) @@ -98,32 +79,22 @@ public String doSignFile(PrivateKeyManager key, String hashAlgorithm, String pat result = sign(key, hashAlgorithm, input); }catch(Exception e) { - error.setError("AE008", e.getMessage()); + error.setError("AS002", e.getMessage()); } return result; } @Override public boolean doVerify(CertificateX509 cert, String plainText, String signature) { - /******** INPUT VERIFICATION - BEGIN ********/ - if(cert == null) - { - error.setError("AE009", "Certificate cannot be null"); - return false; - } - if(plainText == null || plainText.length() == 0 || SecurityUtils.compareStrings("", plainText)) - { - error.setError("AE010", "The plainText value to verify cannot be empty"); - return false; - } - if(signature == null || signature.length() == 0 || SecurityUtils.compareStrings("", signature)) - { - error.setError("AE011", "The signature value to verify cannot be empty"); - return false; - } - /******** INPUT VERIFICATION - END ********/ - + this.error.cleanError(); + /*******INPUT VERIFICATION - BEGIN*******/ + SecurityUtils.validateObjectInput("cert", cert, this.error); + SecurityUtils.validateStringInput("plainText", plainText, this.error); + SecurityUtils.validateStringInput("signature", signature, this.error); + if(this.hasError()) { return false;} + /*******INPUT VERIFICATION - END*******/ + EncodingUtil eu = new EncodingUtil(); byte[] inputText = eu.getBytes(plainText); if (eu.hasError()) { @@ -136,30 +107,21 @@ public boolean doVerify(CertificateX509 cert, String plainText, String signature result = verify(cert, inputStream, signature); }catch(Exception e) { - error.setError("AE012", e.getMessage() ); + error.setError("AS003", e.getMessage() ); } return result; } @Override public boolean doVerifyFile(CertificateX509 cert, String path, String signature) { - /******** INPUT VERIFICATION - BEGIN ********/ - if(cert == null) - { - error.setError("AE013", "Certificate cannot be null"); - return false; - } - if(path == null || path.length() == 0 || SecurityUtils.compareStrings("", path)) - { - error.setError("AE014", "The path value of the faile to verify cannot be empty"); - return false; - } - if(signature == null || signature.length() == 0 || SecurityUtils.compareStrings("", signature)) - { - error.setError("AE015", "The signature value to verify cannot be empty"); - return false; - } - /******** INPUT VERIFICATION - END ********/ + this.error.cleanError(); + + /*******INPUT VERIFICATION - BEGIN*******/ + SecurityUtils.validateObjectInput("cert", cert, this.error); + SecurityUtils.validateStringInput("path", path, this.error); + SecurityUtils.validateStringInput("signature", signature, this.error); + if(this.hasError()) { return false;} + /*******INPUT VERIFICATION - END*******/ boolean result = false; try(InputStream input = SecurityUtils.getFileStream(path, this.error)) @@ -170,13 +132,13 @@ public boolean doVerifyFile(CertificateX509 cert, String path, String signature) result = verify(cert, input, signature); }catch(Exception e) { - error.setError("AE016", e.getMessage()); + error.setError("AS004", e.getMessage()); } return result; } /******** EXTERNAL OBJECT PUBLIC METHODS - END ********/ - + private String sign(PrivateKey key, String hashAlgorithm, InputStream input) { PrivateKeyManager keyMan = (PrivateKeyManager) key; if (keyMan.hasError()) { @@ -195,14 +157,14 @@ private String sign(PrivateKey key, String hashAlgorithm, InputStream input) { try { outputBytes = signer.generateSignature(); } catch (Exception e) { - error.setError("AE01", e.getMessage()); + error.setError("AS005", e.getMessage()); return ""; } String result = ""; try { result = Base64.toBase64String(outputBytes); } catch (Exception e) { - error.setError("AE018", e.getMessage()); + error.setError("AS006", e.getMessage()); return ""; } return result; @@ -232,19 +194,14 @@ private boolean verify(Certificate certificate, InputStream input, String signat try { signatureBytes = Base64.decode(signature); } catch (Exception e) { - error.setError("AE019", e.getMessage()); - return false; - } - - if (signatureBytes == null || signatureBytes.length == 0) { - this.error.setError("AE020", "Error reading signature"); + error.setError("AS007", e.getMessage()); return false; } boolean result = false; try { result = signer.verifySignature(signatureBytes); } catch (Exception e) { - error.setError("AE021", e.getMessage()); + error.setError("AS008", e.getMessage()); return false; } return result; @@ -256,7 +213,7 @@ private void setUpSigner(Signer signer, InputStream input, AsymmetricKeyParamete try { signer.init(toSign, asymmetricKeyParameter); } catch (Exception e) { - error.setError("AE022", e.getMessage()); + error.setError("AS009", e.getMessage()); return; } byte[] buffer = new byte[8192]; @@ -266,7 +223,7 @@ private void setUpSigner(Signer signer, InputStream input, AsymmetricKeyParamete signer.update(buffer, 0, n); } } catch (Exception e) { - error.setError("AE023", e.getMessage()); + error.setError("AS010", e.getMessage()); return; } } diff --git a/GeneXusCryptography/src/main/java/com/genexus/cryptography/checksum/ChecksumCreator.java b/GeneXusCryptography/src/main/java/com/genexus/cryptography/checksum/ChecksumCreator.java index 191aa64..295ca28 100644 --- a/GeneXusCryptography/src/main/java/com/genexus/cryptography/checksum/ChecksumCreator.java +++ b/GeneXusCryptography/src/main/java/com/genexus/cryptography/checksum/ChecksumCreator.java @@ -1,5 +1,10 @@ package com.genexus.cryptography.checksum; +import java.io.ByteArrayInputStream; +import java.io.InputStream; + +import org.bouncycastle.util.encoders.Hex; + import com.genexus.cryptography.checksum.utils.CRCParameters; import com.genexus.cryptography.checksum.utils.ChecksumAlgorithm; import com.genexus.cryptography.checksum.utils.ChecksumInputType; @@ -17,6 +22,15 @@ public ChecksumCreator() { /********EXTERNAL OBJECT PUBLIC METHODS - BEGIN ********/ public String generateChecksum(String input, String inputType, String checksumAlgorithm) { + this.error.cleanError(); + + /*******INPUT VERIFICATION - BEGIN*******/ + SecurityUtils.validateStringInput("input", input, this.error); + SecurityUtils.validateStringInput("inputType", inputType, this.error); + SecurityUtils.validateStringInput("checksumAlgorithm", checksumAlgorithm, this.error); + if(this.hasError()) { return "";}; + /*******INPUT VERIFICATION - END*******/ + ChecksumInputType chksumInputType = ChecksumInputType.getChecksumInputType(inputType, this.error); byte[] inputBytes = ChecksumInputType.getBytes(chksumInputType, input, this.error); if (this.hasError()) { @@ -32,6 +46,16 @@ public String generateChecksum(String input, String inputType, String checksumAl public boolean verifyChecksum(String input, String inputType, String checksumAlgorithm, String digest) { + this.error.cleanError(); + + /*******INPUT VERIFICATION - BEGIN*******/ + SecurityUtils.validateStringInput("input", input, this.error); + SecurityUtils.validateStringInput("inputType", inputType, this.error); + SecurityUtils.validateStringInput("checksumAlgorithm", checksumAlgorithm, this.error); + SecurityUtils.validateStringInput("digest", digest, this.error); + if(this.hasError()) { return false;}; + /*******INPUT VERIFICATION - END*******/ + String result = generateChecksum(input, inputType, checksumAlgorithm); if(SecurityUtils.compareStrings(result, "") || this.hasError()) { @@ -71,38 +95,24 @@ private String calculateHash(byte[] input, ChecksumAlgorithm checksumAlgorithm) return ""; } Hashing hash = new Hashing(); - byte[] digest = hash.calculateHash(alg, input); + byte[] digest = null; + try (InputStream inputStream = new ByteArrayInputStream(input)) { + digest = hash.calculateHash(alg, inputStream); + } catch (Exception e) { + error.setError("CH001", e.getMessage()); + return ""; + } if (hash.hasError()) { this.error = hash.getError(); return ""; } - return toHexaString(digest); + return Hex.toHexString(digest); } private HashAlgorithm getHashAlgorithm(ChecksumAlgorithm checksumAlgorithm) { return HashAlgorithm.getHashAlgorithm(ChecksumAlgorithm.valueOf(checksumAlgorithm, this.error), this.error); } - private String toHexaString(byte[] digest) { - - if (this.error.existsError()) { - return ""; - } - - StringBuilder sb = new StringBuilder(); - for (byte b : digest) { - sb.append(String.format("%02X ", b)); - } - String result = sb.toString().replaceAll("\\s", ""); - if (result == null || result.length() == 0) { - this.error.setError("HS001", "Error encoding hexa"); - return ""; - } - - return result.trim().toUpperCase(); - - } - private long calculateCRC(byte[] input, CRCParameters parms) { long curValue = parms.getInit(); diff --git a/GeneXusCryptography/src/main/java/com/genexus/cryptography/checksum/utils/ChecksumAlgorithm.java b/GeneXusCryptography/src/main/java/com/genexus/cryptography/checksum/utils/ChecksumAlgorithm.java index 21e7661..d95a31d 100644 --- a/GeneXusCryptography/src/main/java/com/genexus/cryptography/checksum/utils/ChecksumAlgorithm.java +++ b/GeneXusCryptography/src/main/java/com/genexus/cryptography/checksum/utils/ChecksumAlgorithm.java @@ -9,9 +9,15 @@ public enum ChecksumAlgorithm { CRC16_DECT_X, CRC16_DNP, CRC16_EN_13757, CRC16_GENIBUS, CRC16_MAXIM, CRC16_MCRF4XX, CRC16_RIELLO, CRC16_T10_DIF, CRC16_TELEDISK, CRC16_TMS_37157, CRC16_USB, CRC_A, CRC16_KERMIT, CRC16_MODBUS, CRC16_X_25, CRC16_XMODEM, CRC32, CRC32_BZIP2, CRC32C, CRC32D, CRC32_MPEG_2, CRC32_POSIX, CRC32Q, CRC32_JAMCRC, CRC32_XFER, MD5, SHA1, SHA256, - SHA512,; + SHA512,NONE; public static ChecksumAlgorithm getChecksumAlgorithm(String checksumAlgorithm, Error error) { + if(error == null) return ChecksumAlgorithm.NONE; + if (checksumAlgorithm == null) + { + error.setError("CHA04", "Unrecognized checksum algorithm"); + return ChecksumAlgorithm.NONE; + } switch (checksumAlgorithm.toUpperCase().trim()) { case "CRC8": return ChecksumAlgorithm.CRC8; @@ -106,12 +112,13 @@ public static ChecksumAlgorithm getChecksumAlgorithm(String checksumAlgorithm, E case "SHA512": return ChecksumAlgorithm.SHA512; default: - error.setError("CA001", "Unrecognized checksum algorithm"); + error.setError("CHA01", "Unrecognized checksum algorithm"); return null; } } public static String valueOf(ChecksumAlgorithm checksumAlgorithm, Error error) { + if (error == null) return null; switch (checksumAlgorithm) { case CRC8: return "CRC8"; @@ -206,7 +213,7 @@ public static String valueOf(ChecksumAlgorithm checksumAlgorithm, Error error) { case SHA512: return "SHA512"; default: - error.setError("CA002", "Unrecognized checksum algorithm"); + error.setError("CHA02", "Unrecognized checksum algorithm"); return null; } } @@ -227,6 +234,7 @@ public static boolean isHash(ChecksumAlgorithm checksumAlgorithm) public static CRCParameters getParameters(ChecksumAlgorithm checksumAlgorithm, Error error) { + if (error == null) return new CRCParameters(0, 0x00, 0x00, false, false, 0x00); switch (checksumAlgorithm) { case CRC8: return new CRCParameters(8, 0x07, 0x00, false, false, 0x00); @@ -313,7 +321,7 @@ public static CRCParameters getParameters(ChecksumAlgorithm checksumAlgorithm, E case CRC32_XFER: return new CRCParameters(32, 0x000000AF, 0x00000000, false, false, 0x0000000); default: - error.setError("CA004", "Unrecognized checksum algorithm"); + error.setError("CHA03", "Unrecognized checksum algorithm"); return null; } } diff --git a/GeneXusCryptography/src/main/java/com/genexus/cryptography/checksum/utils/ChecksumInputType.java b/GeneXusCryptography/src/main/java/com/genexus/cryptography/checksum/utils/ChecksumInputType.java index c8d880c..54c30c4 100644 --- a/GeneXusCryptography/src/main/java/com/genexus/cryptography/checksum/utils/ChecksumInputType.java +++ b/GeneXusCryptography/src/main/java/com/genexus/cryptography/checksum/utils/ChecksumInputType.java @@ -6,9 +6,15 @@ public enum ChecksumInputType { - BASE64, HEX, TXT, ASCII, LOCAL_FILE; + BASE64, HEX, TXT, ASCII, LOCAL_FILE, NONE; public static ChecksumInputType getChecksumInputType(String checksumInputType, Error error) { + if(error == null) return ChecksumInputType.NONE; + if (checksumInputType == null) + { + error.setError("CHI06", "Unrecognized checksum input type"); + return ChecksumInputType.NONE; + } switch (checksumInputType.toUpperCase().trim()) { case "BASE64": return ChecksumInputType.BASE64; @@ -21,12 +27,13 @@ public static ChecksumInputType getChecksumInputType(String checksumInputType, E case "LOCAL_FILE": return ChecksumInputType.LOCAL_FILE; default: - error.setError("CI001", "Unrecognized checksum input type"); + error.setError("CHI01", "Unrecognized checksum input type"); return null; } } public static String valueOf(ChecksumInputType checksumInputType, Error error) { + if (error == null) return ""; switch (checksumInputType) { case BASE64: return "BASE64"; @@ -39,12 +46,13 @@ public static String valueOf(ChecksumInputType checksumInputType, Error error) { case LOCAL_FILE: return "LOCAL_FILE"; default: - error.setError("CI002", "Unrecognized checksum input type"); + error.setError("CHI02", "Unrecognized checksum input type"); return ""; } } public static byte[] getBytes(ChecksumInputType checksumInputType, String input, Error error) { + if (error == null) return null; EncodingUtil eu = new EncodingUtil(); byte[] aux = null; switch (checksumInputType) { @@ -52,11 +60,11 @@ public static byte[] getBytes(ChecksumInputType checksumInputType, String input, try { aux = org.bouncycastle.util.encoders.Base64.decode(input); } catch (Exception e) { - error.setError("CI003", e.getMessage()); + error.setError("CHI03", e.getMessage()); } break; case HEX: - aux = SecurityUtils.getHexa(input, "CI004", error); + aux = SecurityUtils.hexaToByte(input, error); break; case TXT: aux = eu.getBytes(input); @@ -68,14 +76,14 @@ public static byte[] getBytes(ChecksumInputType checksumInputType, String input, try { aux = input.getBytes("US-ASCII"); } catch (Exception e) { - error.setError("CI004", e.getMessage()); + error.setError("CHI04", e.getMessage()); } break; case LOCAL_FILE: aux = SecurityUtils.getFileBytes(input, error); break; default: - error.setError("CI006", "Unrecognized checksum input type"); + error.setError("CHII05", "Unrecognized checksum input type"); break; } return aux; diff --git a/GeneXusCryptography/src/main/java/com/genexus/cryptography/hash/Hashing.java b/GeneXusCryptography/src/main/java/com/genexus/cryptography/hash/Hashing.java index f08c2f1..6b61853 100644 --- a/GeneXusCryptography/src/main/java/com/genexus/cryptography/hash/Hashing.java +++ b/GeneXusCryptography/src/main/java/com/genexus/cryptography/hash/Hashing.java @@ -1,5 +1,7 @@ package com.genexus.cryptography.hash; +import java.io.InputStream; + import org.bouncycastle.crypto.Digest; import org.bouncycastle.crypto.digests.Blake2bDigest; import org.bouncycastle.crypto.digests.Blake2sDigest; @@ -20,14 +22,14 @@ import org.bouncycastle.crypto.digests.SHA384Digest; import org.bouncycastle.crypto.digests.SHA3Digest; import org.bouncycastle.crypto.digests.SHA512Digest; -import org.bouncycastle.crypto.digests.SHAKEDigest; import org.bouncycastle.crypto.digests.SM3Digest; import org.bouncycastle.crypto.digests.TigerDigest; import org.bouncycastle.crypto.digests.WhirlpoolDigest; +import org.bouncycastle.util.encoders.Hex; import com.genexus.cryptography.commons.HashObject; import com.genexus.cryptography.hash.utils.HashAlgorithm; -import com.genexus.securityapicommons.config.EncodingUtil; +import com.genexus.securityapicommons.utils.SecurityUtils; public class Hashing extends HashObject { @@ -50,39 +52,24 @@ public Hashing() { */ public String doHash(String hashAlgorithm, String txtToHash) { this.error.cleanError(); - byte[] resBytes = calculateHash(HashAlgorithm.getHashAlgorithm(hashAlgorithm, this.error), txtToHash); - String result = toHexaString(resBytes); - if (!this.error.existsError()) { - return result; - } - return ""; + + /*******INPUT VERIFICATION - BEGIN*******/ + SecurityUtils.validateStringInput("hashAlgorithm", hashAlgorithm, this.error); + SecurityUtils.validateStringInput("txtToHash", txtToHash, this.error); + if(this.hasError()) { return "";}; + /*******INPUT VERIFICATION - END*******/ + + HashAlgorithm hashAlgorithmObj =HashAlgorithm.getHashAlgorithm(hashAlgorithm, this.error); + InputStream input = SecurityUtils.stringToStream(txtToHash, this.error); + if(this.hasError()) {return null;} + + byte[] resBytes = calculateHash(hashAlgorithmObj, input); + + return this.hasError() ? "": Hex.toHexString(resBytes).toUpperCase(); } /******** EXTERNAL OBJECT PUBLIC METHODS - END ********/ - /** - * @param digest - * byte array - * @return String Hexa respresentation of the byte array digest - */ - private String toHexaString(byte[] digest) { - - if (this.error.existsError()) { - return ""; - } - - StringBuilder sb = new StringBuilder(); - for (byte b : digest) { - sb.append(String.format("%02X ", b)); - } - String result = sb.toString().replaceAll("\\s", ""); - if (result == null || result.length() == 0) { - this.error.setError("HS001", "Error encoding hexa"); - return ""; - } - return result.trim(); - - } /** * @param hashAlgorithm @@ -91,24 +78,20 @@ private String toHexaString(byte[] digest) { * plain text to hcalculate hash * @return byte array of the txtToHash with the algorithm indicated */ - public byte[] calculateHash(HashAlgorithm hashAlgorithm, String txtToHash) { - EncodingUtil eu = new EncodingUtil(); - byte[] inputAsBytes = eu.getBytes(txtToHash); - if (eu.getError().existsError()) { - this.error = eu.getError(); - return null; - } - return calculateHash( hashAlgorithm, inputAsBytes); - } - - public byte[] calculateHash(HashAlgorithm hashAlgorithm, byte[] inputAsBytes) { - - if (this.error.existsError()) { - return null; - } - Digest alg = createHash(hashAlgorithm); + public byte[] calculateHash(HashAlgorithm hashAlgorithm, InputStream input) { + + Digest alg = createHash(hashAlgorithm); + byte[] buffer = new byte[8192]; + int n; byte[] retValue = new byte[alg.getDigestSize()]; - alg.update(inputAsBytes, 0, inputAsBytes.length); + try { + while ((n = input.read(buffer)) > 0) { + alg.update(buffer, 0, n); + } + } catch (Exception e) + { + this.error.setError("HA001", e.getMessage()); + } alg.doFinal(retValue, 0); return retValue; } @@ -192,7 +175,7 @@ public Digest createHash(HashAlgorithm hashAlgorithm) { case WHIRLPOOL: return new WhirlpoolDigest(); default: - this.error.setError("HS002", "Unrecognized HashAlgorithm"); + this.error.setError("HA002", "Unrecognized HashAlgorithm"); return null; } } diff --git a/GeneXusCryptography/src/main/java/com/genexus/cryptography/hash/utils/HashAlgorithm.java b/GeneXusCryptography/src/main/java/com/genexus/cryptography/hash/utils/HashAlgorithm.java index 964694e..5a7194f 100644 --- a/GeneXusCryptography/src/main/java/com/genexus/cryptography/hash/utils/HashAlgorithm.java +++ b/GeneXusCryptography/src/main/java/com/genexus/cryptography/hash/utils/HashAlgorithm.java @@ -20,6 +20,12 @@ public enum HashAlgorithm { * @return HashAlgorithm enum representation */ public static HashAlgorithm getHashAlgorithm(String hashAlgorithm, Error error) { + if(error == null) return HashAlgorithm.NONE; + if (hashAlgorithm == null) + { + error.setError("HAA01", "Unrecognized HashAlgorihm"); + return HashAlgorithm.NONE; + } switch (hashAlgorithm.toUpperCase().trim()) { case "MD5": return HashAlgorithm.MD5; @@ -86,10 +92,10 @@ public static HashAlgorithm getHashAlgorithm(String hashAlgorithm, Error error) case "SHA3-512": return HashAlgorithm.SHA3_512; case "SHAKE_128": - error.setError("HA003", "Not implemented algorithm SHAKE_128"); + error.setError("HAA04", "Not implemented algorithm SHAKE_128"); return null; case "SHAKE_256": - error.setError("HA004", "Not implemented algorithm SHAKE_256"); + error.setError("HAA05", "Not implemented algorithm SHAKE_256"); return null; case "SM3": return HashAlgorithm.SM3; @@ -98,7 +104,7 @@ public static HashAlgorithm getHashAlgorithm(String hashAlgorithm, Error error) case "WHIRLPOOL": return HashAlgorithm.WHIRLPOOL; default: - error.setError("HA001", "Unrecognized HashAlgorihm"); + error.setError("HAA02", "Unrecognized HashAlgorihm"); return null; } } @@ -111,6 +117,7 @@ public static HashAlgorithm getHashAlgorithm(String hashAlgorithm, Error error) * @return String name value of HashAlgorithm */ public static String valueOf(HashAlgorithm hashAlgorithm, Error error) { + if(error == null) return "Unrecognized algorithm"; switch (hashAlgorithm) { case MD5: return "MD5"; @@ -183,7 +190,7 @@ public static String valueOf(HashAlgorithm hashAlgorithm, Error error) { case WHIRLPOOL: return "WHIRLPOOL"; default: - error.setError("HA002", "Unrecognized HashAlgorihm"); + error.setError("HAA03", "Unrecognized HashAlgorihm"); return "Unrecognized algorithm"; } } diff --git a/GeneXusCryptography/src/main/java/com/genexus/cryptography/mac/Cmac.java b/GeneXusCryptography/src/main/java/com/genexus/cryptography/mac/Cmac.java index 54f62b0..8ff0ecc 100644 --- a/GeneXusCryptography/src/main/java/com/genexus/cryptography/mac/Cmac.java +++ b/GeneXusCryptography/src/main/java/com/genexus/cryptography/mac/Cmac.java @@ -1,14 +1,16 @@ package com.genexus.cryptography.mac; +import java.io.InputStream; + import org.bouncycastle.crypto.BlockCipher; import org.bouncycastle.crypto.CipherParameters; import org.bouncycastle.crypto.macs.CMac; import org.bouncycastle.crypto.params.KeyParameter; +import org.bouncycastle.util.encoders.Hex; import com.genexus.cryptography.commons.CmacObject; import com.genexus.cryptography.symmetric.SymmetricBlockCipher; import com.genexus.cryptography.symmetric.utils.SymmetricBlockAlgorithm; -import com.genexus.securityapicommons.config.EncodingUtil; import com.genexus.securityapicommons.utils.SecurityUtils; public class Cmac extends CmacObject { @@ -21,98 +23,98 @@ public Cmac() { @Override public String calculate(String plainText, String key, String algorithm, int macSize) { - if (!isValidAlgorithm(algorithm)) { - this.error.setError("CM001", "Invalid Symmetric block algorithm for CMAC"); - return ""; - } + this.error.cleanError(); + + /*******INPUT VERIFICATION - BEGIN*******/ + SecurityUtils.validateStringInput("plainText", plainText, this.error); + SecurityUtils.validateStringInput("key", key, this.error); + SecurityUtils.validateStringInput("algorithm", algorithm, this.error); + if(this.hasError()) { return "";}; + /*******INPUT VERIFICATION - END*******/ + SymmetricBlockAlgorithm symmetricBlockAlgorithm = SymmetricBlockAlgorithm.getSymmetricBlockAlgorithm(algorithm, this.error); + InputStream input = SecurityUtils.stringToStream(plainText, this.error); + byte[] byteKey = SecurityUtils.hexaToByte(key, this.error); + if(this.hasError() ) { return "";} + SymmetricBlockCipher symCipher = new SymmetricBlockCipher(); BlockCipher blockCipher = symCipher.getCipherEngine(symmetricBlockAlgorithm); - if (symCipher.hasError()) { + + if(symCipher.hasError()) + { this.error = symCipher.getError(); return ""; } - if (macSize > blockCipher.getBlockSize() * 8) { - this.error.setError("CM002", "The mac length must be less or equal than the algorithm block size."); + + + int blockSize = blockCipher.getBlockSize() * 8; + + if (macSize > blockSize) { + this.error.setError("CM001", "The mac length must be less or equal than the algorithm block size."); return ""; } - byte[] byteKey = SecurityUtils.getHexa(key, "CM003", this.error); - if (this.hasError()) { + + if (blockSize != 64 && blockSize != 128) { + this.error.setError("CM002", "The block size must be 64 or 128 bits for CMAC. Wrong symmetric algorithm"); return ""; } - EncodingUtil eu = new EncodingUtil(); - byte[] byteInput = eu.getBytes(plainText); + + byte[] resBytes = calculate(input, byteKey, macSize, blockCipher); - CipherParameters params = new KeyParameter(byteKey); - - org.bouncycastle.crypto.macs.CMac mac = null; - if (macSize != 0) { - mac = new CMac(blockCipher, macSize); - } else { - mac = new CMac(blockCipher); - } - try { - mac.init(params); - } catch (Exception e) { - this.error.setError("CM004", e.getMessage()); - return ""; - } - byte[] resBytes = new byte[mac.getMacSize()]; - mac.update(byteInput, 0, byteInput.length); - mac.doFinal(resBytes, 0); - String result = toHexaString(resBytes); - if (!this.error.existsError()) { - return result; - } - return ""; + return this.hasError() ? "": Hex.toHexString(resBytes); } @Override public boolean verify(String plainText, String key, String mac, String algorithm, int macSize) { + this.error.cleanError(); + + /*******INPUT VERIFICATION - BEGIN*******/ + SecurityUtils.validateStringInput("plainText", plainText, this.error); + SecurityUtils.validateStringInput("key", key, this.error); + SecurityUtils.validateStringInput("mac", mac, this.error); + SecurityUtils.validateStringInput("algorithm", algorithm, this.error); + if(this.hasError()) { return false;}; + /*******INPUT VERIFICATION - END*******/ + String res = calculate(plainText, key, algorithm, macSize); return SecurityUtils.compareStrings(res, mac); } /******** EXTERNAL OBJECT PUBLIC METHODS - END ********/ - /** - * @param digest byte array - * @return String Hexa respresentation of the byte array digest - */ - private String toHexaString(byte[] digest) { + + private byte[] calculate(InputStream input, byte[] key , int macSize, BlockCipher blockCipher) { - if (this.error.existsError()) { - return ""; - } + CipherParameters params = new KeyParameter(key); - StringBuilder sb = new StringBuilder(); - for (byte b : digest) { - sb.append(String.format("%02X ", b)); - } - String result = sb.toString().replaceAll("\\s", ""); - if (result == null || result.length() == 0) { - this.error.setError("HS001", "Error encoding hexa"); - return ""; - } - return result.trim(); - - } + org.bouncycastle.crypto.macs.CMac mac = null; - private boolean isValidAlgorithm(String algorithm) { - SymmetricBlockAlgorithm symmetricBlockAlgorithm = SymmetricBlockAlgorithm.getSymmetricBlockAlgorithm(algorithm, - this.error); - int blockSize = SymmetricBlockAlgorithm.getBlockSize(symmetricBlockAlgorithm, this.error); - if (this.hasError()) { + mac = macSize !=0 ? new CMac(blockCipher, macSize): new CMac(blockCipher); - return false; + try { + mac.init(params); + } catch (Exception e) { + this.error.setError("CM003", e.getMessage()); + return null; } - if (blockSize != 64 && blockSize != 128) { - - return false; + byte[] retValue = new byte[mac.getMacSize()]; + byte[] buffer = new byte[8192]; + int n; + try { + while ((n = input.read(buffer)) > 0) { + mac.update(buffer, 0, n); + } + mac.doFinal(retValue, 0); + } catch (Exception e) + { + this.error.setError("CM004", e.getMessage()); + return null; } - - return true; + + return retValue; + } + } diff --git a/GeneXusCryptography/src/main/java/com/genexus/cryptography/mac/Hmac.java b/GeneXusCryptography/src/main/java/com/genexus/cryptography/mac/Hmac.java index 9d65c3a..78c3362 100644 --- a/GeneXusCryptography/src/main/java/com/genexus/cryptography/mac/Hmac.java +++ b/GeneXusCryptography/src/main/java/com/genexus/cryptography/mac/Hmac.java @@ -1,13 +1,15 @@ package com.genexus.cryptography.mac; +import java.io.InputStream; + import org.bouncycastle.crypto.Digest; import org.bouncycastle.crypto.macs.HMac; import org.bouncycastle.crypto.params.KeyParameter; +import org.bouncycastle.util.encoders.Hex; import com.genexus.cryptography.commons.HmacObject; import com.genexus.cryptography.hash.Hashing; import com.genexus.cryptography.hash.utils.HashAlgorithm; -import com.genexus.securityapicommons.config.EncodingUtil; import com.genexus.securityapicommons.utils.SecurityUtils; public class Hmac extends HmacObject { @@ -19,69 +21,73 @@ public Hmac() { /******** EXTERNAL OBJECT PUBLIC METHODS - BEGIN ********/ @Override public String calculate(String plainText, String password, String algorithm) { - byte[] pass = SecurityUtils.getHexa(password, "HS002", this.error); - if (this.hasError()) { - return ""; - } - EncodingUtil eu = new EncodingUtil(); - byte[] inputBytes = eu.getBytes(plainText); - if (this.hasError()) { - return ""; - } - Hashing hash = new Hashing(); - HashAlgorithm alg = HashAlgorithm.getHashAlgorithm(algorithm, this.error); - if (this.hasError()) { - return ""; - } - Digest digest = hash.createHash(alg); - HMac engine = new HMac(digest); - try { - engine.init(new KeyParameter(pass)); - } catch (Exception e) { - this.error.setError("HS003", e.getMessage()); - return ""; - } - byte[] resBytes = new byte[engine.getMacSize()]; - engine.update(inputBytes, 0, inputBytes.length); - engine.doFinal(resBytes, 0); - - String result = toHexaString(resBytes); - if (!this.error.existsError()) { - return result; - } - return ""; - + this.error.cleanError(); + + /*******INPUT VERIFICATION - BEGIN*******/ + SecurityUtils.validateStringInput("plainText", plainText, this.error); + SecurityUtils.validateStringInput("password", password, this.error); + SecurityUtils.validateStringInput("algorithm", algorithm, this.error); + if(this.hasError()) { return "";}; + /*******INPUT VERIFICATION - END*******/ + + byte[] pass = SecurityUtils.hexaToByte(password, this.error); + HashAlgorithm hashAlgorithm = HashAlgorithm.getHashAlgorithm(algorithm, this.error); + InputStream input = SecurityUtils.stringToStream(plainText, this.error); + if (this.hasError()) { return ""; } + + byte[] resBytes = calculate(input, pass, hashAlgorithm); + + return this.hasError() ? "": Hex.toHexString(resBytes); + } @Override public boolean verify(String plainText, String password, String mac, String algorithm) { + this.error.cleanError(); + + /*******INPUT VERIFICATION - BEGIN*******/ + SecurityUtils.validateStringInput("plainText", plainText, this.error); + SecurityUtils.validateStringInput("password", password, this.error); + SecurityUtils.validateStringInput("algorithm", algorithm, this.error); + SecurityUtils.validateStringInput("mac", mac, this.error); + if(this.hasError()) { return false;}; + /*******INPUT VERIFICATION - END*******/ + String res = calculate(plainText, password, algorithm); return SecurityUtils.compareStrings(res, mac); } /******** EXTERNAL OBJECT PUBLIC METHODS - END ********/ - /** - * @param digest byte array - * @return String Hexa respresentation of the byte array digest - */ - private String toHexaString(byte[] digest) { - - if (this.error.existsError()) { - return ""; - } - - StringBuilder sb = new StringBuilder(); - for (byte b : digest) { - sb.append(String.format("%02X ", b)); + + private byte[] calculate(InputStream input, byte[] password, HashAlgorithm algorithm) { + + Digest digest = new Hashing().createHash(algorithm); + if (this.hasError()) { return null; } + + HMac engine = new HMac(digest); + try { + engine.init(new KeyParameter(password)); + } catch (Exception e) { + this.error.setError("HM001", e.getMessage()); + return null; } - String result = sb.toString().replaceAll("\\s", ""); - if (result == null || result.length() == 0) { - this.error.setError("HS001", "Error encoding hexa"); - return ""; + + byte[] buffer = new byte[8192]; + int n; + byte[] resBytes = new byte[engine.getMacSize()]; + try { + while ((n = input.read(buffer)) > 0) { + engine.update(buffer, 0, n); + } + engine.doFinal(resBytes, 0); + } catch (Exception e) + { + this.error.setError("HM002", e.getMessage()); + return null; } - return result.trim(); - + + return resBytes; } } diff --git a/GeneXusCryptography/src/main/java/com/genexus/cryptography/passwordDerivation/Argon2HashType.java b/GeneXusCryptography/src/main/java/com/genexus/cryptography/passwordDerivation/Argon2HashType.java index 5212733..72c173a 100644 --- a/GeneXusCryptography/src/main/java/com/genexus/cryptography/passwordDerivation/Argon2HashType.java +++ b/GeneXusCryptography/src/main/java/com/genexus/cryptography/passwordDerivation/Argon2HashType.java @@ -16,7 +16,7 @@ public static Argon2HashType getArgon2HashType(String argon2HashType, Error erro case "ARGON2_id": return Argon2HashType.ARGON2_id; default: - error.setError("A2001", "Unrecognized Arggon2HashType"); + error.setError("PDH01", "Unrecognized Argon2HashType"); return null; } @@ -31,7 +31,7 @@ public static String valueOf(Argon2HashType argon2HashType, Error error) { case ARGON2_id: return "ARGON2_id"; default: - error.setError("A2002", "Unrecognized Arggon2HashType"); + error.setError("PDH02", "Unrecognized Argon2HashType"); return ""; } } @@ -45,7 +45,7 @@ public static int getArgon2Parameter(Argon2HashType argon2HashType, Error error) case ARGON2_id: return Argon2Parameters.ARGON2_id; default: - error.setError("A2003", "Unrecognized Arggon2HashType"); + error.setError("PDH03", "Unrecognized Argon2HashType"); return 0; } } diff --git a/GeneXusCryptography/src/main/java/com/genexus/cryptography/passwordDerivation/Argon2Version.java b/GeneXusCryptography/src/main/java/com/genexus/cryptography/passwordDerivation/Argon2Version.java index 8a5a946..fd0120b 100644 --- a/GeneXusCryptography/src/main/java/com/genexus/cryptography/passwordDerivation/Argon2Version.java +++ b/GeneXusCryptography/src/main/java/com/genexus/cryptography/passwordDerivation/Argon2Version.java @@ -15,7 +15,7 @@ public static Argon2Version getArgon2Version(String argon2Version, Error error) case "ARGON2_VERSION_13": return Argon2Version.ARGON2_VERSION_13; default: - error.setError("AR001", "Unrecognized Argon2Version"); + error.setError("PDV01", "Unrecognized Argon2Version"); return null; } } @@ -27,7 +27,7 @@ public static String valueOf(Argon2Version argon2Version, Error error) { case ARGON2_VERSION_13: return "ARGON2_VERSION_13"; default: - error.setError("AR002", "Unrecognized Argon2Version"); + error.setError("PDV02", "Unrecognized Argon2Version"); return ""; } } @@ -39,7 +39,7 @@ public static int getVersionParameter(Argon2Version argon2Version, Error error) case ARGON2_VERSION_13: return Argon2Parameters.ARGON2_VERSION_13; default: - error.setError("AR003", "Unrecognized Argon2Version"); + error.setError("PDV03", "Unrecognized Argon2Version"); return 0; } } diff --git a/GeneXusCryptography/src/main/java/com/genexus/cryptography/passwordDerivation/PasswordDerivation.java b/GeneXusCryptography/src/main/java/com/genexus/cryptography/passwordDerivation/PasswordDerivation.java index 771e60e..fbf6eb5 100644 --- a/GeneXusCryptography/src/main/java/com/genexus/cryptography/passwordDerivation/PasswordDerivation.java +++ b/GeneXusCryptography/src/main/java/com/genexus/cryptography/passwordDerivation/PasswordDerivation.java @@ -6,10 +6,10 @@ import org.bouncycastle.crypto.params.Argon2Parameters; import org.bouncycastle.util.Strings; import org.bouncycastle.util.encoders.Base64; -import org.bouncycastle.util.encoders.Hex; import com.genexus.cryptography.commons.PasswordDerivationObject; import com.genexus.securityapicommons.config.EncodingUtil; +import com.genexus.securityapicommons.utils.SecurityUtils; /** * @author sgrampone @@ -45,23 +45,32 @@ public PasswordDerivation() { public String doGenerateSCrypt(String password, String salt, int CPUCost, int blockSize, int parallelization, int keyLenght) { this.error.cleanError(); - if (!areSCRyptValidParameters(CPUCost, blockSize, parallelization)) { - return ""; - } + + /*******INPUT VERIFICATION - BEGIN*******/ + SecurityUtils.validateStringInput("password", password, this.error); + SecurityUtils.validateStringInput("salt", salt, this.error); + if (keyLenght == 0) {this.error.setError("PD005", "Parameter keyLenght cannot be 0");} + if(this.hasError()) { return "";}; + /*******INPUT VERIFICATION - END*******/ + EncodingUtil eu = new EncodingUtil(); - if (eu.getError().existsError()) { - this.error = eu.getError(); - return ""; - } - byte[] encryptedBytes = SCrypt.generate(eu.getBytes(password), Hex.decode(salt), CPUCost, blockSize, - parallelization, keyLenght); - String result = Strings.fromByteArray(Base64.encode(encryptedBytes)); - if (result == null || result.length() == 0) { - this.error.setError("PD009", "SCrypt generation error"); + byte[] bytePassword = eu.getBytes(password); + if(eu.hasError()) { this.error = eu.getError(); } + + byte[] byteSalt = SecurityUtils.hexaToByte(salt, this.error); + if(this.hasError()) {return "";} + + byte[] encryptedBytes = null; + try { + encryptedBytes = SCrypt.generate(bytePassword, byteSalt, CPUCost, blockSize, + parallelization, keyLenght); + }catch(Exception e) + { + this.error.setError("PD001", e.getMessage()); return ""; } - this.error.cleanError(); - return result; + return Strings.fromByteArray(Base64.encode(encryptedBytes)); + } /** @@ -75,6 +84,13 @@ public String doGenerateSCrypt(String password, String salt, int CPUCost, int bl * String UTF-8 to use as salt */ public String doGenerateDefaultSCrypt(String password, String salt) { + + /*******INPUT VERIFICATION - BEGIN*******/ + SecurityUtils.validateStringInput("password", password, this.error); + SecurityUtils.validateStringInput("salt", salt, this.error); + if(this.hasError()) { return "";}; + /*******INPUT VERIFICATION - END*******/ + int N = 16384; int r = 8; int p = 1; @@ -95,18 +111,32 @@ public String doGenerateDefaultSCrypt(String password, String salt) { */ public String doGenerateBcrypt(String password, String salt, int cost) { this.error.cleanError(); - if (!areBCryptValidParameters(password, salt, cost)) { - return ""; - } + + /*******INPUT VERIFICATION - BEGIN*******/ + SecurityUtils.validateStringInput("password", password, this.error); + SecurityUtils.validateStringInput("salt", salt, this.error); + if(this.hasError()) { return "";}; + /*******INPUT VERIFICATION - END*******/ + EncodingUtil eu = new EncodingUtil(); - byte[] encryptedBytes = BCrypt.generate(eu.getBytes(password), Hex.decode(salt), cost); - String result = Strings.fromByteArray(Base64.encode(encryptedBytes)); - if (result == null || result.length() == 0) { - this.error.setError("PD010", "Bcrypt generation error"); + byte[] bytePassword = eu.getBytes(password); + if(eu.hasError()) {this.error = eu.getError(); } + + byte[] byteSalt = SecurityUtils.hexaToByte(salt, this.error); + if(this.hasError()) { return ""; } + + byte[] encryptedBytes = null; + + try { + encryptedBytes = BCrypt.generate(bytePassword, byteSalt, cost); + }catch(Exception e) + { + this.error.setError("PD002", e.getMessage()); return ""; } - this.error.cleanError(); - return result; + + return Strings.fromByteArray(Base64.encode(encryptedBytes)); + } /** @@ -120,135 +150,59 @@ public String doGenerateBcrypt(String password, String salt, int cost) { * @return String Base64 hashed password to store */ public String doGenerateDefaultBcrypt(String password, String salt) { + + /*******INPUT VERIFICATION - BEGIN*******/ + SecurityUtils.validateStringInput("password", password, this.error); + SecurityUtils.validateStringInput("salt", salt, this.error); + if(this.hasError()) { return "";}; + /*******INPUT VERIFICATION - END*******/ + int cost = 6; return doGenerateBcrypt(password, salt, cost); } public String doGenerateArgon2(String argon2Version10, String argon2HashType, int iterations, int memory, int parallelism, String password, String salt, int hashLength) { - if (!areArgon2ValidParameters(iterations, parallelism, hashLength)) { - return ""; - } + this.error.cleanError(); + + /*******INPUT VERIFICATION - BEGIN*******/ + SecurityUtils.validateStringInput("argon2Version10", argon2Version10, this.error); + SecurityUtils.validateStringInput("argon2HashType", argon2HashType, this.error); + SecurityUtils.validateStringInput("password", password, this.error); + SecurityUtils.validateStringInput("salt", salt, this.error); + if(hashLength == 0) {this.error.setError("PD006", "Parameter hashLength cannot be 0");} + if(this.hasError()) { return "";}; + /*******INPUT VERIFICATION - END*******/ + Argon2Version ver_aux = Argon2Version.getArgon2Version(argon2Version10, this.error); int version = Argon2Version.getVersionParameter(ver_aux, this.error); - if (this.hasError()) { - return ""; - } Argon2HashType hash_aux = Argon2HashType.getArgon2HashType(argon2HashType, this.error); - int hashType = Argon2HashType.getArgon2Parameter(hash_aux, this.error); - if (this.hasError()) { - return ""; - } - + int hashType = Argon2HashType.getArgon2Parameter(hash_aux, this.error); EncodingUtil eu = new EncodingUtil(); byte[] bytePass = eu.getBytes(password); - if (eu.hasError()) { - this.error = eu.getError(); - return ""; - } + if(eu.hasError()) { this.error = eu.getError(); } + byte[] byteSalt = SecurityUtils.hexaToByte(salt, this.error); + if(this.hasError()) { return ""; } Argon2Parameters.Builder builder = new Argon2Parameters.Builder(hashType).withVersion(version) .withIterations(iterations).withMemoryPowOfTwo(memory).withParallelism(parallelism) - .withSalt(Hex.decode(salt)); + .withSalt(byteSalt); Argon2BytesGenerator dig = new Argon2BytesGenerator(); - dig.init(builder.build()); byte[] res = new byte[hashLength]; + + try { + dig.init(builder.build()); dig.generateBytes(bytePass, res); - String result = Strings.fromByteArray(Base64.encode(res)); - if (result == null || result.length() == 0) { - this.error.setError("PD012", "Argon2 generation error"); + }catch(Exception e) + { + this.error.setError("PD003", e.getMessage()); return ""; } - this.error.cleanError(); - return result; - } - - /******** EXTERNAL OBJECT PUBLIC METHODS - END ********/ + return Strings.fromByteArray(Base64.encode(res)); - /** - * @param pwd - * password String UTF-8 to hash. the password bytes (up to 72 bytes) - * to use for this invocation. - * @param salt - * salt String UTF-8 to salt. The salt lenght must be 128 bits - * @param cost - * cost The cost of the bcrypt function grows as 2^cost. Legal values - * are 4..31 inclusive. - * @return true if BCrypt parameters are correct - */ - private boolean areBCryptValidParameters(String pwd, String salt, int cost) { - EncodingUtil eu = new EncodingUtil(); - byte[] pwdBytes = eu.getBytes(pwd); - byte[] saltBytes = Hex.decode(salt); - if (saltBytes.length * 8 != 128) { - this.error.setError("PD008", "The salt lenght must be 128 bits"); - return false; - } - if (cost < 4 || cost > 31) { - this.error.setError("PD007", - "The cost of the bcrypt function grows as 2^cost. Legal values are 4..31 inclusive."); - return false; - } - if (pwdBytes.length > 72) { - this.error.setError("PD006", "The password bytes (up to 72 bytes) to use for this invocation."); - return false; - } - return true; - } - - /** - * @param number - * int number to test - * @return true if number is power of 2 - */ - private static boolean isPowerOfTwo(int number) { - return number > 0 && ((number & (number - 1)) == 0); - } - - /** - * @param CPUCost - * CPUCost must be larger than 1, a power of 2 and less than 2^(128 * - * blockSize / 8) - * @param blockSize - * The blockSize must be >= 1 - * @param parallelization - * Parallelization must be a positive integer less than or equal to - * Integer.MAX_VALUE / (128 * blockSize * 8) - * @return true if SCrypt parameters are correct - */ - private boolean areSCRyptValidParameters(int CPUCost, int blockSize, int parallelization) { - if (blockSize < 1) { - this.error.setError("PD005", "The blockSize must be >= 1"); - return false; - } - if (CPUCost < 2 || CPUCost >= Math.pow(2, 128 * blockSize / 8) || !isPowerOfTwo(CPUCost)) { - this.error.setError("PD004", - "CPUCost must be larger than 1, a power of 2 and less than 2^(128 * blockSize / 8)"); - return false; - } - if (parallelization <= 0 || parallelization > Integer.MAX_VALUE / (128 * blockSize * 8)) { - this.error.setError("PD003", - "Parallelization must be a positive integer less than or equal to Integer.MAX_VALUE / (128 * blockSize * 8)"); - return false; - } - return true; } - private boolean areArgon2ValidParameters(int iterations, int parallelism, int hashLength) { - if (parallelism < 1 || parallelism >= 16777216) { - this.error.setError("PD012", "Parallelism parameter must be >= 1 and < 16777216"); - return false; - } - if (iterations < 1) { - this.error.setError("PD013", "Must be 1 iteration at least"); - return false; - } - if (hashLength < 4) { - this.error.setError("PD014", "The output hash length must be >= 4"); - return false; - } - return true; - } + /******** EXTERNAL OBJECT PUBLIC METHODS - END ********/ } diff --git a/GeneXusCryptography/src/main/java/com/genexus/cryptography/passwordDerivation/PasswordDerivationAlgorithm.java b/GeneXusCryptography/src/main/java/com/genexus/cryptography/passwordDerivation/PasswordDerivationAlgorithm.java index 05ce171..394aeb6 100644 --- a/GeneXusCryptography/src/main/java/com/genexus/cryptography/passwordDerivation/PasswordDerivationAlgorithm.java +++ b/GeneXusCryptography/src/main/java/com/genexus/cryptography/passwordDerivation/PasswordDerivationAlgorithm.java @@ -7,7 +7,7 @@ * */ public enum PasswordDerivationAlgorithm { - SCrypt, Bcrypt,Argon2; + SCrypt, Bcrypt,Argon2, NONE; /** * Mapping between String name and PasswordDerivationAlgorithm enum @@ -21,6 +21,12 @@ public enum PasswordDerivationAlgorithm { */ public static PasswordDerivationAlgorithm getPasswordDerivationAlgorithm(String passwordDerivationAlgorithm, Error error) { + if (error == null) return PasswordDerivationAlgorithm.NONE; + if(passwordDerivationAlgorithm == null) + { + error.setError("PDA03", "Unrecognized PasswordDerivationAlgorithm"); + return PasswordDerivationAlgorithm.NONE; + } switch (passwordDerivationAlgorithm.trim()) { case "SCrypt": return PasswordDerivationAlgorithm.SCrypt; @@ -29,7 +35,7 @@ public static PasswordDerivationAlgorithm getPasswordDerivationAlgorithm(String case "Argon2": return PasswordDerivationAlgorithm.Argon2; default: - error.setError("PD001", "Unrecognized PasswordDerivationAlgorithm"); + error.setError("PDA01", "Unrecognized PasswordDerivationAlgorithm"); return null; } } @@ -42,6 +48,7 @@ public static PasswordDerivationAlgorithm getPasswordDerivationAlgorithm(String * @return PasswordDerivationAlgorithm value in String */ public static String valueOf(PasswordDerivationAlgorithm passwordDerivationAlgorithm, Error error) { + if(error == null) return "Unrecognized algorithm"; switch (passwordDerivationAlgorithm) { case SCrypt: return "SCrypt"; @@ -50,7 +57,7 @@ public static String valueOf(PasswordDerivationAlgorithm passwordDerivationAlgor case Argon2: return "Argon2"; default: - error.setError("PD002", "Unrecognized PasswordDerivationAlgorithm"); + error.setError("PDA02", "Unrecognized PasswordDerivationAlgorithm"); return "Unrecognized algorithm"; } } diff --git a/GeneXusCryptography/src/main/java/com/genexus/cryptography/symmetric/SymmetricBlockCipher.java b/GeneXusCryptography/src/main/java/com/genexus/cryptography/symmetric/SymmetricBlockCipher.java index c2c6a31..aa5dcff 100644 --- a/GeneXusCryptography/src/main/java/com/genexus/cryptography/symmetric/SymmetricBlockCipher.java +++ b/GeneXusCryptography/src/main/java/com/genexus/cryptography/symmetric/SymmetricBlockCipher.java @@ -2,8 +2,6 @@ import org.bouncycastle.crypto.BlockCipher; import org.bouncycastle.crypto.BufferedBlockCipher; -import org.bouncycastle.crypto.DataLengthException; -import org.bouncycastle.crypto.InvalidCipherTextException; import org.bouncycastle.crypto.engines.AESEngine; import org.bouncycastle.crypto.engines.BlowfishEngine; import org.bouncycastle.crypto.engines.CAST5Engine; @@ -49,6 +47,7 @@ import org.bouncycastle.crypto.params.AEADParameters; import org.bouncycastle.crypto.params.KeyParameter; import org.bouncycastle.crypto.params.ParametersWithIV; +import org.bouncycastle.util.Strings; import org.bouncycastle.util.encoders.Base64; import com.genexus.cryptography.commons.SymmetricBlockCipherObject; @@ -89,53 +88,26 @@ public SymmetricBlockCipher() { public String doAEADEncrypt(String symmetricBlockAlgorithm, String symmetricBlockMode, String key, int macSize, String nonce, String plainText) { this.error.cleanError(); - SymmetricBlockAlgorithm algorithm = SymmetricBlockAlgorithm.getSymmetricBlockAlgorithm(symmetricBlockAlgorithm, - this.error); - SymmetricBlockMode mode = SymmetricBlockMode.getSymmetricBlockMode(symmetricBlockMode, this.error); - if (this.error.existsError()) { - return ""; - } - BlockCipher engine = getCipherEngine(algorithm); - AEADBlockCipher bbc = getAEADCipherMode(engine, mode); - if (this.error.existsError() && !(this.error.getCode().compareToIgnoreCase("SB016") == 0)) { - return ""; - } - - byte[] nonceBytes = SecurityUtils.getHexa(nonce, "SB024", this.error); - byte[] keyBytes = SecurityUtils.getHexa(key, "SB024", this.error); - if (this.hasError()) { - return ""; - } - KeyParameter keyParam = new KeyParameter(keyBytes); - AEADParameters AEADparams = new AEADParameters(keyParam, macSize, nonceBytes); - try { - bbc.init(true, AEADparams); - } catch (Exception e) { - this.error.setError("SB029", e.getMessage()); - return ""; - } + /*******INPUT VERIFICATION - BEGIN*******/ + SecurityUtils.validateStringInput("symmetricBlockAlgorithm", symmetricBlockAlgorithm, this.error); + SecurityUtils.validateStringInput("symmetricBlockMode", symmetricBlockMode, this.error); + SecurityUtils.validateStringInput("key", key, this.error); + SecurityUtils.validateStringInput("nonce", nonce, this.error); + SecurityUtils.validateStringInput("plainText", plainText, this.error); + if(this.hasError()) { return "";}; + /*******INPUT VERIFICATION - END*******/ + EncodingUtil eu = new EncodingUtil(); - byte[] inputBytes = eu.getBytes(plainText); - if (eu.getError().existsError()) { - this.error = eu.getError(); - return ""; - } - byte[] outputBytes = new byte[bbc.getOutputSize(inputBytes.length)]; - int length = bbc.processBytes(inputBytes, 0, inputBytes.length, outputBytes, 0); - try { - bbc.doFinal(outputBytes, length); - } catch (DataLengthException | IllegalStateException | InvalidCipherTextException e) { - this.error.setError("SB010", "AEAD encryption exception"); - e.printStackTrace(); - } - String result = new String(Base64.encode(outputBytes)); - if (result == null || result.length() == 0) { - this.error.setError("SB011", "Error encoding base64"); - return ""; - } - this.error.cleanError(); - return result.trim(); + byte[] txtBytes = eu.getBytes(plainText); + if(eu.hasError()) {this.error = eu.getError(); } + if (this.hasError()) { return ""; } + + byte[] encryptedBytes = setUp(symmetricBlockAlgorithm, symmetricBlockMode, null,nonce, key, txtBytes, macSize, true, true); + if (this.hasError()) { return ""; } + + return Strings.fromByteArray(Base64.encode(encryptedBytes)).trim(); + } /** @@ -154,49 +126,35 @@ public String doAEADEncrypt(String symmetricBlockAlgorithm, String symmetricBloc public String doAEADDecrypt(String symmetricBlockAlgorithm, String symmetricBlockMode, String key, int macSize, String nonce, String encryptedInput) { this.error.cleanError(); - SymmetricBlockAlgorithm algorithm = SymmetricBlockAlgorithm.getSymmetricBlockAlgorithm(symmetricBlockAlgorithm, - this.error); - SymmetricBlockMode mode = SymmetricBlockMode.getSymmetricBlockMode(symmetricBlockMode, this.error); - if (this.error.existsError()) { - return ""; - } - BlockCipher engine = getCipherEngine(algorithm); - AEADBlockCipher bbc = getAEADCipherMode(engine, mode); - if (this.error.existsError() && !(this.error.getCode().compareToIgnoreCase("SB016") == 0)) { - return ""; - } - byte[] nonceBytes = SecurityUtils.getHexa(nonce, "SB025", this.error); - byte[] keyBytes = SecurityUtils.getHexa(key, "SB025", this.error); - if (this.hasError()) { - return ""; - } - - KeyParameter keyParam = new KeyParameter(keyBytes); - AEADParameters AEADparams = new AEADParameters(keyParam, macSize, nonceBytes); + + /*******INPUT VERIFICATION - BEGIN*******/ + SecurityUtils.validateStringInput("symmetricBlockAlgorithm", symmetricBlockAlgorithm, this.error); + SecurityUtils.validateStringInput("symmetricBlockMode", symmetricBlockMode, this.error); + SecurityUtils.validateStringInput("key", key, this.error); + SecurityUtils.validateStringInput("nonce", nonce, this.error); + SecurityUtils.validateStringInput("encryptedInput", encryptedInput, this.error); + if(this.hasError()) { return "";}; + /*******INPUT VERIFICATION - END*******/ + + byte[] input = null; try { - bbc.init(false, AEADparams); - } catch (Exception e) { - this.error.setError("SB030", e.getMessage()); + input = Base64.decode(encryptedInput); + }catch(Exception e) + { + this.error.setError("SB001", e.getMessage()); return ""; } - byte[] out2 = Base64.decode(encryptedInput); - byte[] comparisonBytes = new byte[bbc.getOutputSize(out2.length)]; - int length = bbc.processBytes(out2, 0, out2.length, comparisonBytes, 0); - try { - bbc.doFinal(comparisonBytes, length); - } catch (DataLengthException | IllegalStateException | InvalidCipherTextException e) { - this.error.setError("SB012", "AEAD decryption exception"); - e.printStackTrace(); - } + + byte[] decryptedBytes = setUp(symmetricBlockAlgorithm, symmetricBlockMode, null, nonce, key, input, macSize, false, true); + if (this.hasError()) {return "";} + EncodingUtil eu = new EncodingUtil(); - String result = eu.getString(comparisonBytes); - if (eu.getError().existsError()) { + String result = eu.getString(decryptedBytes); + if (eu.hasError()) { this.error = eu.getError(); return ""; } - this.error.cleanError(); return result.trim(); - } /** @@ -215,64 +173,28 @@ public String doAEADDecrypt(String symmetricBlockAlgorithm, String symmetricBloc public String doEncrypt(String symmetricBlockAlgorithm, String symmetricBlockMode, String symmetricBlockPadding, String key, String IV, String plainText) { this.error.cleanError(); - SymmetricBlockAlgorithm algorithm = SymmetricBlockAlgorithm.getSymmetricBlockAlgorithm(symmetricBlockAlgorithm, - this.error); - SymmetricBlockMode mode = SymmetricBlockMode.getSymmetricBlockMode(symmetricBlockMode, this.error); - SymmetricBlockPadding padding = SymmetricBlockPadding.getSymmetricBlockPadding(symmetricBlockPadding, - this.error); - - if (this.error.existsError()) { - return ""; - } - BufferedBlockCipher bbc = getCipher(algorithm, mode, padding); - if (this.error.existsError() && !(this.error.getCode().compareToIgnoreCase("SB016") == 0)) { - return ""; - } - byte[] byteIV = SecurityUtils.getHexa(IV, "SB022", this.error); - byte[] byteKey = SecurityUtils.getHexa(key, "SB022", this.error); - if (this.hasError()) { - return ""; - } - - KeyParameter keyParam = new KeyParameter(byteKey); - - if (SymmetricBlockMode.ECB != mode && SymmetricBlockMode.OPENPGPCFB != mode) { - ParametersWithIV keyParamWithIV = new ParametersWithIV(keyParam, byteIV); - try { - bbc.init(true, keyParamWithIV); - } catch (Exception e) { - this.error.setError("SB025", e.getMessage()); - return ""; - } - } else { - try { - bbc.init(true, keyParam); - } catch (Exception e) { - this.error.setError("SB026", e.getMessage()); - return ""; - } - } + + /*******INPUT VERIFICATION - BEGIN*******/ + SecurityUtils.validateStringInput("symmetricBlockAlgorithm", symmetricBlockAlgorithm, this.error); + SecurityUtils.validateStringInput("symmetricBlockMode", symmetricBlockMode, this.error); + SecurityUtils.validateStringInput("symmetricBlockPadding", symmetricBlockPadding, this.error); + SecurityUtils.validateStringInput("key", key, this.error); + SecurityUtils.validateStringInput("IV", IV, this.error); + SecurityUtils.validateStringInput("plainText", plainText, this.error); + if(this.hasError()) { return "";}; + /*******INPUT VERIFICATION - END*******/ + EncodingUtil eu = new EncodingUtil(); - byte[] inputBytes = eu.getBytes(plainText);// plainText.getBytes(); + byte[] inputBytes = eu.getBytes(plainText); if (eu.hasError()) { this.error = eu.getError(); return ""; } - byte[] outputBytes = new byte[bbc.getOutputSize(inputBytes.length)]; - int length = bbc.processBytes(inputBytes, 0, inputBytes.length, outputBytes, 0); - try { - bbc.doFinal(outputBytes, length); - } catch (DataLengthException | IllegalStateException | InvalidCipherTextException e) { - this.error.setError("SB013", "Block encryption exception"); - e.printStackTrace(); - } - String result = new String(Base64.encode(outputBytes)); - if (result == null || result.length() == 0) { - this.error.setError("SB014", "Error encoding base64"); - return ""; - } - this.error.cleanError(); - return result.trim(); + + byte[] encryptedBytes = setUp(symmetricBlockAlgorithm, symmetricBlockMode, symmetricBlockPadding, IV, key, inputBytes, 0, true, false); + if(this.hasError()){ return ""; } + + return Strings.fromByteArray(Base64.encode(encryptedBytes)).trim(); } /** @@ -291,58 +213,37 @@ public String doEncrypt(String symmetricBlockAlgorithm, String symmetricBlockMod public String doDecrypt(String symmetricBlockAlgorithm, String symmetricBlockMode, String symmetricBlockPadding, String key, String IV, String encryptedInput) { this.error.cleanError(); - SymmetricBlockAlgorithm algorithm = SymmetricBlockAlgorithm.getSymmetricBlockAlgorithm(symmetricBlockAlgorithm, - this.error); - SymmetricBlockMode mode = SymmetricBlockMode.getSymmetricBlockMode(symmetricBlockMode, this.error); - SymmetricBlockPadding padding = SymmetricBlockPadding.getSymmetricBlockPadding(symmetricBlockPadding, - this.error); - if (this.error.existsError()) { - return ""; - } - BufferedBlockCipher bbc = getCipher(algorithm, mode, padding); - if (this.error.existsError() && !(this.error.getCode().compareToIgnoreCase("SB016") == 0)) { - return ""; - } - byte[] bytesKey = SecurityUtils.getHexa(key, "SB023", this.error); - byte[] bytesIV = SecurityUtils.getHexa(IV, "SB023", this.error); - if (this.hasError()) { - return ""; - } - KeyParameter keyParam = new KeyParameter(bytesKey); - if (SymmetricBlockMode.ECB != mode && SymmetricBlockMode.OPENPGPCFB != mode) { - ParametersWithIV keyParamWithIV = new ParametersWithIV(keyParam, bytesIV); - try { - bbc.init(false, keyParamWithIV); - } catch (Exception e) { - this.error.setError("SB027", e.getMessage()); - return ""; - } - } else { - try { - bbc.init(false, keyParam); - } catch (Exception e) { - this.error.setError("SB028", e.getMessage()); - return ""; - } - } - - byte[] out2 = Base64.decode(encryptedInput); - byte[] comparisonBytes = new byte[bbc.getOutputSize(out2.length)]; - int length = bbc.processBytes(out2, 0, out2.length, comparisonBytes, 0); + + /*******INPUT VERIFICATION - BEGIN*******/ + SecurityUtils.validateStringInput("symmetricBlockAlgorithm", symmetricBlockAlgorithm, this.error); + SecurityUtils.validateStringInput("symmetricBlockMode", symmetricBlockMode, this.error); + SecurityUtils.validateStringInput("symmetricBlockPadding", symmetricBlockPadding, this.error); + SecurityUtils.validateStringInput("key", key, this.error); + SecurityUtils.validateStringInput("IV", IV, this.error); + SecurityUtils.validateStringInput("encryptedInput", encryptedInput, this.error); + if(this.hasError()) { return "";}; + /*******INPUT VERIFICATION - END*******/ + + byte[] input = null; try { - bbc.doFinal(comparisonBytes, length); - } catch (DataLengthException | IllegalStateException | InvalidCipherTextException e) { - this.error.setError("SB015", "Block decryption exception"); - e.printStackTrace(); + input = Base64.decode(encryptedInput); + }catch(Exception e) + { + this.error.setError("SB002", e.getMessage()); + return ""; } + + byte[] decryptedBytes = setUp(symmetricBlockAlgorithm, symmetricBlockMode, symmetricBlockPadding, IV, key, input, 0, false, false); + if(this.hasError()) { return ""; } + EncodingUtil eu = new EncodingUtil(); - String result = eu.getString(comparisonBytes); - if (eu.getError().existsError()) { + String result = eu.getString(decryptedBytes); + if (eu.hasError()) { this.error = eu.getError(); return ""; } - this.error.cleanError(); return result.trim(); + } /******** EXTERNAL OBJECT PUBLIC METHODS - END ********/ @@ -502,7 +403,7 @@ public BlockCipher getCipherEngine(SymmetricBlockAlgorithm algorithm) { engine = new XTEAEngine(); break; default: - this.error.setError("SB020", "Cipher " + algorithm + " not recognised."); + this.error.setError("SB003", "Unrecognized symmetric block algoritm"); break; } return engine; @@ -539,7 +440,7 @@ private BlockCipherPadding getPadding(SymmetricBlockPadding padding) { paddingCipher = new ZeroBytePadding(); break; default: - this.error.setError("SB018", "Cipher " + padding + " not recognised."); + this.error.setError("SB004", "Unrecognized symmetric block padding."); break; } return paddingCipher; @@ -568,7 +469,7 @@ private AEADBlockCipher getAEADCipherMode(BlockCipher blockCipher, SymmetricBloc bc = new KCCMBlockCipher(blockCipher); break; default: - this.error.setError("SB017", "AEADCipher " + mode + " not recognised."); + this.error.setError("SB005", "Unrecognized symmetric AEAD mode"); break; } return bc; @@ -611,19 +512,96 @@ private BlockCipher getCipherMode(BlockCipher blockCipher, SymmetricBlockMode mo bc = new OpenPGPCFBBlockCipher(blockCipher); break; case SIC: - if (blockCipher.getBlockSize() < 16) { - this.error.setError("SB016", - "Warning: SIC-Mode can become a twotime-pad if the blocksize of the cipher is too small. Use a cipher with a block size of at least 128 bits (e.g. AES)"); - } blockCipher = new SICBlockCipher(blockCipher); break; default: - this.error.setError("SB021", "Ciphermode " + mode + " not recognised."); + this.error.setError("SB006", "Unrecognized symmetric block mode"); break; } return bc; } + + private byte[] setUp(String symmetricBlockAlgorithm, String symmetricBlockMode, String symmetricBlockPadding, String nonce, String key, byte[] input, int macSize, boolean toEncrypt, boolean isAEAD) + { + SymmetricBlockAlgorithm algorithm = SymmetricBlockAlgorithm.getSymmetricBlockAlgorithm(symmetricBlockAlgorithm, + this.error); + SymmetricBlockMode mode = SymmetricBlockMode.getSymmetricBlockMode(symmetricBlockMode, this.error); + SymmetricBlockPadding padding = null; + if(!isAEAD) + { + padding = SymmetricBlockPadding.getSymmetricBlockPadding(symmetricBlockPadding, + this.error); + } + + byte[] nonceBytes = SecurityUtils.hexaToByte(nonce, this.error); + byte[] keyBytes = SecurityUtils.hexaToByte(key, this.error); + + if(this.hasError()) { return null; } + + return isAEAD? encryptAEAD(algorithm, mode, keyBytes, nonceBytes, input, macSize, toEncrypt): encrypt(algorithm, mode, padding, keyBytes, nonceBytes, input, toEncrypt); + + } + + + private byte[] encryptAEAD(SymmetricBlockAlgorithm algorithm, SymmetricBlockMode mode, byte[] key, byte[] nonce, byte[] txt, int macSize, boolean toEncrypt) + { + BlockCipher engine = getCipherEngine(algorithm); + AEADBlockCipher bbc = getAEADCipherMode(engine, mode); + if(this.hasError()) { return null; } + + KeyParameter keyParam = new KeyParameter(key); + AEADParameters AEADparams = new AEADParameters(keyParam, macSize, nonce); + + try { + bbc.init(toEncrypt, AEADparams); + } catch (Exception e) { + this.error.setError("SB007", e.getMessage()); + return null; + } + + byte[] outputBytes = new byte[bbc.getOutputSize(txt.length)]; + try { + + int length = bbc.processBytes(txt, 0, txt.length, outputBytes, 0); + bbc.doFinal(outputBytes, length); + } catch (Exception e) { + this.error.setError("SB008", e.getMessage()); + return null; + } + return outputBytes; + } + + + + private byte[] encrypt(SymmetricBlockAlgorithm algorithm, SymmetricBlockMode mode, SymmetricBlockPadding padding, byte[] key, byte[] iv, byte[] input, boolean toEncrypt) + { + if(padding == null) {return null;} + + BufferedBlockCipher bbc = getCipher(algorithm, mode, padding); + KeyParameter keyParam = new KeyParameter(key); + if(this.hasError()) { return null; } + try { + if (SymmetricBlockMode.ECB != mode && SymmetricBlockMode.OPENPGPCFB != mode) { + ParametersWithIV keyParamWithIV = new ParametersWithIV(keyParam, iv); + bbc.init(toEncrypt, keyParamWithIV); + }else { + bbc.init(toEncrypt, keyParam); + } + }catch(Exception e) { + this.error.setError("SB009", e.getMessage()); + return null; + } + byte[] outputBytes = new byte[bbc.getOutputSize(input.length)]; + try { + int length = bbc.processBytes(input, 0, input.length, outputBytes, 0); + bbc.doFinal(outputBytes, length); + } catch (Exception e) { + this.error.setError("SB010", e.getMessage()); + return null; + } + return outputBytes; + } } diff --git a/GeneXusCryptography/src/main/java/com/genexus/cryptography/symmetric/SymmetricStreamCipher.java b/GeneXusCryptography/src/main/java/com/genexus/cryptography/symmetric/SymmetricStreamCipher.java index 59f5ac9..3921bb2 100644 --- a/GeneXusCryptography/src/main/java/com/genexus/cryptography/symmetric/SymmetricStreamCipher.java +++ b/GeneXusCryptography/src/main/java/com/genexus/cryptography/symmetric/SymmetricStreamCipher.java @@ -11,6 +11,7 @@ import org.bouncycastle.crypto.engines.XSalsa20Engine; import org.bouncycastle.crypto.params.KeyParameter; import org.bouncycastle.crypto.params.ParametersWithIV; +import org.bouncycastle.util.Strings; import org.bouncycastle.util.encoders.Base64; import com.genexus.cryptography.commons.SymmectricStreamCipherObject; @@ -45,58 +46,25 @@ public SymmetricStreamCipher() { */ public String doEncrypt(String symmetricStreamAlgorithm, String key, String IV, String plainText) { this.error.cleanError(); - SymmetricStreamAlgorithm algorithm = SymmetricStreamAlgorithm - .getSymmetricStreamAlgorithm(symmetricStreamAlgorithm, this.error); - - if (this.error.existsError()) { - return ""; - } - - StreamCipher engine = getCipherEngine(algorithm); - if (this.error.existsError()) { - return ""; - } - - byte[] keyBytes = SecurityUtils.getHexa(key, "SS007", this.error); - byte[] ivBytes = SecurityUtils.getHexa(IV, "SS007", this.error); - if (this.hasError()) { - return ""; - } - KeyParameter keyParam = new KeyParameter(keyBytes); - if (SymmetricStreamAlgorithm.usesIV(algorithm, this.error)) { - if (!this.error.existsError()) { - ParametersWithIV keyParamWithIV = new ParametersWithIV(keyParam, ivBytes); - try { - engine.init(true, keyParamWithIV); - } catch (Exception e) { - this.error.setError("SS008", e.getMessage()); - return ""; - } - } - } else { - try { - engine.init(true, keyParam); - } catch (Exception e) { - this.error.setError("SS009", e.getLocalizedMessage()); - return ""; - } - } + + /*******INPUT VERIFICATION - BEGIN*******/ + SecurityUtils.validateStringInput("symmetricStreamAlgorithm", symmetricStreamAlgorithm, this.error); + SecurityUtils.validateStringInput("key", key, this.error); + SecurityUtils.validateStringInput("plainText", plainText, this.error); + if(this.hasError()) { return "";}; + /*******INPUT VERIFICATION - END*******/ + EncodingUtil eu = new EncodingUtil(); byte[] input = eu.getBytes(plainText); - if (eu.getError().existsError()) { + if (eu.hasError()) { this.error = eu.getError(); return ""; } - byte[] output = new byte[input.length]; - engine.processBytes(input, 0, input.length, output, 0); - String result = new String(Base64.encode(output)); - if (result == null || result.length() == 0) { - this.error.setError("SS004", "Stream encryption exception"); - return ""; - } - this.error.cleanError(); - return result; - + + byte[] encryptedBytes = setUp(symmetricStreamAlgorithm, key, IV, input, true); + if(this.hasError()) {return null; } + + return Strings.fromByteArray(Base64.encode(encryptedBytes)).trim(); } /** @@ -112,58 +80,33 @@ public String doEncrypt(String symmetricStreamAlgorithm, String key, String IV, */ public String doDecrypt(String symmetricStreamAlgorithm, String key, String IV, String encryptedInput) { this.error.cleanError(); - SymmetricStreamAlgorithm algorithm = SymmetricStreamAlgorithm - .getSymmetricStreamAlgorithm(symmetricStreamAlgorithm, this.error); - - if (this.error.existsError()) { + + /*******INPUT VERIFICATION - BEGIN*******/ + SecurityUtils.validateStringInput("symmetricStreamAlgorithm", symmetricStreamAlgorithm, this.error); + SecurityUtils.validateStringInput("key", key, this.error); + SecurityUtils.validateStringInput("encryptedInput", encryptedInput, this.error); + if(this.hasError()) { return "";}; + /*******INPUT VERIFICATION - END*******/ + + byte[] input = null; + try { + input = Base64.decode(encryptedInput); + }catch(Exception e) + { + this.error.setError("SS001", e.getMessage()); return ""; } - - StreamCipher engine = getCipherEngine(algorithm); - if (this.error.existsError()) { - return ""; - } - byte[] keyBytes = SecurityUtils.getHexa(key, "SS010", this.error); - byte[] ivBytes = SecurityUtils.getHexa(IV, "SS010", this.error); - if (this.hasError()) { - return ""; - } - - KeyParameter keyParam = new KeyParameter(keyBytes); - if (SymmetricStreamAlgorithm.usesIV(algorithm, this.error)) { - if (!this.error.existsError()) { - ParametersWithIV keyParamWithIV = new ParametersWithIV(keyParam, ivBytes); - try { - engine.init(false, keyParamWithIV); - } catch (Exception e) { - this.error.setError("SS011", e.getMessage()); - return ""; - } - } - } else { - try { - engine.init(false, keyParam); - } catch (Exception e) { - this.error.setError("SS012", e.getMessage()); - return ""; - } - } - - byte[] input = Base64.decode(encryptedInput); - byte[] output = new byte[input.length]; - engine.processBytes(input, 0, input.length, output, 0); - if (output == null || output.length == 0) { - this.error.setError("SS006", "Stream decryption exception"); - } + + byte[] decryptedBytes = setUp(symmetricStreamAlgorithm, key, IV, input, false); + if(this.hasError()) {return null; } + EncodingUtil eu = new EncodingUtil(); - String result = eu.getString(output).trim(); - if (eu.getError().existsError()) { + String result = eu.getString(decryptedBytes); + if (eu.hasError()) { this.error = eu.getError(); return ""; } - this.error.cleanError(); - return result; - + return result.trim(); } /******** EXTERNAL OBJECT PUBLIC METHODS - END ********/ @@ -173,9 +116,6 @@ public String doDecrypt(String symmetricStreamAlgorithm, String key, String IV, * @return StreamCipher with the algorithm Stream Engine */ private StreamCipher getCipherEngine(SymmetricStreamAlgorithm algorithm) { - // System.out.print("algorithm: "+ SymmetricStreamAlgorithm.valueOf(algorithm, - // error)); - StreamCipher engine = null; switch (algorithm) { @@ -204,10 +144,54 @@ private StreamCipher getCipherEngine(SymmetricStreamAlgorithm algorithm) { engine = new VMPCEngine(); break; default: - this.error.setError("SS005", "Cipher " + algorithm + " not recognised."); + this.error.setError("SS002", "Unrecognized stream cipher algorithm"); break; } return engine; } + + private byte[] setUp(String symmetricStreamAlgorithm, String key, String IV, byte[] input, boolean toEncrypt) + { + byte[] keyBytes = SecurityUtils.hexaToByte(key, this.error); + byte[] ivBytes = SecurityUtils.hexaToByte(IV, this.error); + SymmetricStreamAlgorithm algorithm = SymmetricStreamAlgorithm + .getSymmetricStreamAlgorithm(symmetricStreamAlgorithm, this.error); + if(this.hasError()) { return null; } + + return encrypt(algorithm, keyBytes, ivBytes, input, toEncrypt); + + } + + private byte[] encrypt(SymmetricStreamAlgorithm algorithm, byte[] key, byte[] IV, byte[] input, boolean toEncrypt) + { + StreamCipher engine = getCipherEngine(algorithm); + if(this.hasError()) { return null; } + + + KeyParameter keyParam = new KeyParameter(key); + + try { + if (SymmetricStreamAlgorithm.usesIV(algorithm, this.error)) + { + ParametersWithIV keyParamWithIV = new ParametersWithIV(keyParam, IV); + engine.init(toEncrypt, keyParamWithIV); + }else { + engine.init(toEncrypt, keyParam); + } + }catch(Exception e) { + this.error.setError("SS003", e.getMessage()); + return null; + } + + + byte[] output = new byte[input.length]; + try { + engine.processBytes(input, 0, input.length, output, 0); + }catch(Exception e) { + this.error.setError("SS004", e.getMessage()); + return null; + } + return output; + } } diff --git a/GeneXusCryptography/src/main/java/com/genexus/cryptography/symmetric/utils/SymmetricBlockAlgorithm.java b/GeneXusCryptography/src/main/java/com/genexus/cryptography/symmetric/utils/SymmetricBlockAlgorithm.java index 3d37cf4..2912e5b 100644 --- a/GeneXusCryptography/src/main/java/com/genexus/cryptography/symmetric/utils/SymmetricBlockAlgorithm.java +++ b/GeneXusCryptography/src/main/java/com/genexus/cryptography/symmetric/utils/SymmetricBlockAlgorithm.java @@ -8,7 +8,7 @@ */ public enum SymmetricBlockAlgorithm { - AES, BLOWFISH, CAMELLIA, CAST5, CAST6, DES, TRIPLEDES, DSTU7624_128, DSTU7624_256, DSTU7624_512, GOST28147, NOEKEON, RC2, RC532, RC564, RC6, RIJNDAEL_128, RIJNDAEL_160, RIJNDAEL_192, RIJNDAEL_224, RIJNDAEL_256, SEED, SERPENT, SKIPJACK, SM4, THREEFISH_256, THREEFISH_512, THREEFISH_1024, TWOFISH, XTEA, TEA; + AES, BLOWFISH, CAMELLIA, CAST5, CAST6, DES, TRIPLEDES, DSTU7624_128, DSTU7624_256, DSTU7624_512, GOST28147, NOEKEON, RC2, RC532, RC564, RC6, RIJNDAEL_128, RIJNDAEL_160, RIJNDAEL_192, RIJNDAEL_224, RIJNDAEL_256, SEED, SERPENT, SKIPJACK, SM4, THREEFISH_256, THREEFISH_512, THREEFISH_1024, TWOFISH, XTEA, TEA, NONE; /** * Mapping between String name and SymmetricBlockAlgorithm enum representation @@ -20,6 +20,12 @@ public enum SymmetricBlockAlgorithm { * @return SymmetricBlockAlgorithm enum representaton */ public static SymmetricBlockAlgorithm getSymmetricBlockAlgorithm(String symmetricBlockAlgorithm, Error error) { + if(error == null) return SymmetricBlockAlgorithm.NONE; + if(symmetricBlockAlgorithm == null) + { + error.setError("SBA05", "Unrecognized SymmetricBlockAlgorithm"); + return SymmetricBlockAlgorithm.NONE; + } switch (symmetricBlockAlgorithm.toUpperCase().trim()) { case "AES": return SymmetricBlockAlgorithm.AES; @@ -84,7 +90,7 @@ public static SymmetricBlockAlgorithm getSymmetricBlockAlgorithm(String symmetri case "TEA": return SymmetricBlockAlgorithm.TEA; default: - error.setError("SB001", "Unrecognized SymmetricBlockAlgorithm"); + error.setError("SBA01", "Unrecognized SymmetricBlockAlgorithm"); return null; } @@ -98,6 +104,8 @@ public static SymmetricBlockAlgorithm getSymmetricBlockAlgorithm(String symmetri * @return value of SymmetricBlockAlgorithm in String */ public static String valueOf(SymmetricBlockAlgorithm symmetricBlockAlgorithm, Error error) { + if (error == null) return "SymmetricBlockAlgorithm"; + switch (symmetricBlockAlgorithm) { case AES: return "AES"; @@ -162,7 +170,7 @@ public static String valueOf(SymmetricBlockAlgorithm symmetricBlockAlgorithm, Er case TEA: return "TEA"; default: - error.setError("SB002", "Unrecognized SymmetricBlockAlgorithm"); + error.setError("SBA02", "Unrecognized SymmetricBlockAlgorithm"); return "SymmetricBlockAlgorithm"; } } @@ -175,6 +183,8 @@ public static String valueOf(SymmetricBlockAlgorithm symmetricBlockAlgorithm, Er * @return the specific block size for the algorithm, algorithm unknown if 0 */ public static int getBlockSize(SymmetricBlockAlgorithm algorithm, Error error) { + if (error == null) return 0; + switch (algorithm) { case BLOWFISH: @@ -217,7 +227,7 @@ public static int getBlockSize(SymmetricBlockAlgorithm algorithm, Error error) { case THREEFISH_1024: return 1024; default: - error.setError("SB003", "Unrecognized SymmetricBlockAlgorithm"); + error.setError("SBA03", "Unrecognized SymmetricBlockAlgorithm"); return 0; } } @@ -298,7 +308,7 @@ protected static int[] getKeySize(SymmetricBlockAlgorithm algorithm, Error error keySize[2] = 1024; break; default: - error.setError("SB004", "Unrecognized SymmetricBlockAlgorithm"); + error.setError("SBA04", "Unrecognized SymmetricBlockAlgorithm"); } return keySize; } diff --git a/GeneXusCryptography/src/main/java/com/genexus/cryptography/symmetric/utils/SymmetricBlockMode.java b/GeneXusCryptography/src/main/java/com/genexus/cryptography/symmetric/utils/SymmetricBlockMode.java index 7b45e6c..7c9aa10 100644 --- a/GeneXusCryptography/src/main/java/com/genexus/cryptography/symmetric/utils/SymmetricBlockMode.java +++ b/GeneXusCryptography/src/main/java/com/genexus/cryptography/symmetric/utils/SymmetricBlockMode.java @@ -21,6 +21,12 @@ public enum SymmetricBlockMode { * @return SymmetricBlockMode enum representation */ public static SymmetricBlockMode getSymmetricBlockMode(String symmetricBlockMode, Error error) { + if (error == null) return SymmetricBlockMode.NONE; + if(symmetricBlockMode == null) + { + error.setError("SBM04", "Unrecognized SymmetricBlockMode"); + return SymmetricBlockMode.NONE; + } switch (symmetricBlockMode.toUpperCase().trim()) { case "ECB": return SymmetricBlockMode.ECB; @@ -51,7 +57,7 @@ public static SymmetricBlockMode getSymmetricBlockMode(String symmetricBlockMode case "AEAD_CCM": return SymmetricBlockMode.AEAD_CCM; default: - error.setError("SB005", "Unrecognized SymmetricBlockMode"); + error.setError("SBM01", "Unrecognized SymmetricBlockMode"); return null; } } @@ -64,6 +70,8 @@ public static SymmetricBlockMode getSymmetricBlockMode(String symmetricBlockMode * @return SymmetricBlockMode name value in String */ public static String valueOf(SymmetricBlockMode symmetricBlockMode, Error error) { + if (error == null) return "Unrecognized operation mode"; + switch (symmetricBlockMode) { case ECB: return "ECB"; @@ -94,7 +102,7 @@ public static String valueOf(SymmetricBlockMode symmetricBlockMode, Error error) case AEAD_CCM: return "AEAD_CCM"; default: - error.setError("SB006", "Unrecognized SymmetricBlockMode"); + error.setError("SBM02", "Unrecognized SymmetricBlockMode"); return "Unrecognized operation mode"; } } @@ -107,6 +115,8 @@ public static String valueOf(SymmetricBlockMode symmetricBlockMode, Error error) * @return boolean true if operation mode is AEAD type */ public static boolean isAEAD(SymmetricBlockMode symmetricBlockMode, Error error) { + if (error == null) return false; + switch (symmetricBlockMode) { case AEAD_EAX: case AEAD_GCM: @@ -114,7 +124,7 @@ public static boolean isAEAD(SymmetricBlockMode symmetricBlockMode, Error error) case AEAD_CCM: return true; default: - error.setError("SB007", "Unrecognized Symmetric AEAD BlockMode"); + error.setError("SBM03", "Unrecognized Symmetric AEAD BlockMode"); return false; } } diff --git a/GeneXusCryptography/src/main/java/com/genexus/cryptography/symmetric/utils/SymmetricBlockPadding.java b/GeneXusCryptography/src/main/java/com/genexus/cryptography/symmetric/utils/SymmetricBlockPadding.java index 647b7ed..98227b8 100644 --- a/GeneXusCryptography/src/main/java/com/genexus/cryptography/symmetric/utils/SymmetricBlockPadding.java +++ b/GeneXusCryptography/src/main/java/com/genexus/cryptography/symmetric/utils/SymmetricBlockPadding.java @@ -20,6 +20,13 @@ public enum SymmetricBlockPadding { * @return SymmetricBlockPadding enum representation */ public static SymmetricBlockPadding getSymmetricBlockPadding(String symmetricBlockPadding, Error error) { + if (error == null) return SymmetricBlockPadding.NOPADDING; + if(symmetricBlockPadding == null) + { + error.setError("SBP03", "Unrecognized SymmetricBlockPadding"); + return SymmetricBlockPadding.NOPADDING; + } + switch (symmetricBlockPadding.toUpperCase().trim()) { case "NOPADDING": return SymmetricBlockPadding.NOPADDING; @@ -36,7 +43,7 @@ public static SymmetricBlockPadding getSymmetricBlockPadding(String symmetricBlo case "WITHCTS": return SymmetricBlockPadding.WITHCTS; default: - error.setError("SB008", "Unrecognized SymmetricBlockPadding"); + error.setError("SBP01", "Unrecognized SymmetricBlockPadding"); return null; } } @@ -49,6 +56,8 @@ public static SymmetricBlockPadding getSymmetricBlockPadding(String symmetricBlo * @return String name value of SymmetricBlockPadding */ public static String valueOf(SymmetricBlockPadding symmetricBlockPadding, Error error) { + if(error == null) return "Unrecognized block padding"; + switch (symmetricBlockPadding) { case NOPADDING: return "NOPADDING"; @@ -65,7 +74,7 @@ public static String valueOf(SymmetricBlockPadding symmetricBlockPadding, Error case WITHCTS: return "WITHCTS"; default: - error.setError("SB009", "Unrecognized SymmetricBlockPadding"); + error.setError("SBP02", "Unrecognized SymmetricBlockPadding"); return "Unrecognized block padding"; } } diff --git a/GeneXusCryptography/src/main/java/com/genexus/cryptography/symmetric/utils/SymmetricStreamAlgorithm.java b/GeneXusCryptography/src/main/java/com/genexus/cryptography/symmetric/utils/SymmetricStreamAlgorithm.java index ffc00d9..78ae28f 100644 --- a/GeneXusCryptography/src/main/java/com/genexus/cryptography/symmetric/utils/SymmetricStreamAlgorithm.java +++ b/GeneXusCryptography/src/main/java/com/genexus/cryptography/symmetric/utils/SymmetricStreamAlgorithm.java @@ -7,7 +7,7 @@ * */ public enum SymmetricStreamAlgorithm { - RC4, HC128, HC256, CHACHA20, SALSA20, XSALSA20, ISAAC, VMPC,; + RC4, HC128, HC256, CHACHA20, SALSA20, XSALSA20, ISAAC, VMPC, NONE; /** * Mapping between String name and SymmetricStreamAlgorithm enum representation @@ -19,6 +19,13 @@ public enum SymmetricStreamAlgorithm { * @return SymmetricStreamAlgorithm enum representation */ public static SymmetricStreamAlgorithm getSymmetricStreamAlgorithm(String symmetricStreamAlgorithm, Error error) { + if (error == null) return SymmetricStreamAlgorithm.NONE; + if( symmetricStreamAlgorithm == null) + { + error.setError("SSA05", "Unrecognized SymmetricStreamAlgorithm"); + return SymmetricStreamAlgorithm.NONE; + } + switch (symmetricStreamAlgorithm.toUpperCase().trim()) { case "RC4": return SymmetricStreamAlgorithm.RC4; @@ -37,7 +44,7 @@ public static SymmetricStreamAlgorithm getSymmetricStreamAlgorithm(String symmet case "VMPC": return SymmetricStreamAlgorithm.VMPC; default: - error.setError("SS001", "Unrecognized SymmetricStreamAlgorithm"); + error.setError("SSA01", "Unrecognized SymmetricStreamAlgorithm"); return null; } } @@ -50,6 +57,8 @@ public static SymmetricStreamAlgorithm getSymmetricStreamAlgorithm(String symmet * @return String SymmetrcStreamAlgorithm name value */ public static String valueOf(SymmetricStreamAlgorithm symmetrcStreamAlgorithm, Error error) { + if(error == null) return "Unrecognized algorithm"; + switch (symmetrcStreamAlgorithm) { case RC4: return "RC4"; @@ -68,7 +77,7 @@ public static String valueOf(SymmetricStreamAlgorithm symmetrcStreamAlgorithm, E case VMPC: return "VMPC"; default: - error.setError("SS002", "Unrecognized SymmetricStreamAlgorithm"); + error.setError("SSA02", "Unrecognized SymmetricStreamAlgorithm"); return "Unrecognized algorithm"; } } @@ -82,6 +91,8 @@ public static String valueOf(SymmetricStreamAlgorithm symmetrcStreamAlgorithm, E * fixed values */ protected static int[] getKeySize(SymmetricStreamAlgorithm algorithm, Error error) { + if (error == null) return null; + int[] keySize = new int[3]; switch (algorithm) { case RC4: @@ -115,7 +126,7 @@ protected static int[] getKeySize(SymmetricStreamAlgorithm algorithm, Error erro keySize[2] = 6144; break; default: - error.setError("SS003", "Unrecognized SymmetricStreamAlgorithm"); + error.setError("SSA03", "Unrecognized SymmetricStreamAlgorithm"); break; } return keySize; @@ -141,7 +152,7 @@ public static boolean usesIV(SymmetricStreamAlgorithm algorithm, Error error) { case VMPC: return true; default: - error.setError("SS007", "Unrecognized SymmetricStreamAlgorithm"); + error.setError("SSA04", "Unrecognized SymmetricStreamAlgorithm"); return true; } diff --git a/SecurityAPICommons/src/main/java/com/genexus/securityapicommons/encoders/Base64Encoder.java b/SecurityAPICommons/src/main/java/com/genexus/securityapicommons/encoders/Base64Encoder.java index b0c3eb7..cb19b55 100644 --- a/SecurityAPICommons/src/main/java/com/genexus/securityapicommons/encoders/Base64Encoder.java +++ b/SecurityAPICommons/src/main/java/com/genexus/securityapicommons/encoders/Base64Encoder.java @@ -25,13 +25,21 @@ public Base64Encoder() { * @return Base64 String text encoded */ public String toBase64(String text) { - byte[] textBytes = new EncodingUtil().getBytes(text); - String result = new String(Base64.encode(textBytes)); - if (result == null || result.length() == 0) { - this.error.setError("B64001", "Error encoding base64"); + this.error.cleanError(); + EncodingUtil eu = new EncodingUtil(); + byte[] textBytes = eu.getBytes(text); + if(eu.hasError()) { + this.error = eu.getError(); + return ""; + } + String result = ""; + try { + result = Base64.toBase64String(textBytes); + }catch(Exception e) + { + this.error.setError("BS001", e.getMessage()); return ""; } - this.error.cleanError(); return result; } @@ -41,14 +49,22 @@ public String toBase64(String text) { * @return String UTF-8 plain text from Base64 */ public String toPlainText(String base64Text) { - byte[] bytes = Base64.decode(base64Text); - - String result = new EncodingUtil().getString(bytes); - if (result == null || result.length() == 0) { - this.error.setError("B64002", "Error decoding base64"); + this.error.cleanError(); + byte[] bytes; + try { + bytes = Base64.decode(base64Text); + }catch(Exception e) + { + this.error.setError("BS002", e.getMessage()); + return ""; + } + EncodingUtil eu = new EncodingUtil(); + String result = eu.getString(bytes); + if(eu.hasError()) + { + this.error = eu.getError(); return ""; } - this.error.cleanError(); return result; } @@ -58,17 +74,23 @@ public String toPlainText(String base64Text) { * @return String Hexa representation of base64Text */ public String toStringHexa(String base64Text) { - byte[] bytes = Base64.decode(base64Text); - StringBuilder sb = new StringBuilder(); - for (byte b : bytes) { - sb.append(String.format("%02X ", b)); + this.error.cleanError(); + byte[] bytes; + try { + bytes = Base64.decode(base64Text); + }catch(Exception e) + { + this.error.setError("BS003", e.getMessage()); + return ""; } - String result = sb.toString().replaceAll("\\s", ""); - if (result == null || result.length() == 0) { - this.error.setError("B64003", "Error decoding base64 to hexa"); + String result = ""; + try { + result = Hex.toHexString(bytes).toUpperCase(); + }catch(Exception e) + { + this.error.setError("BS004", e.getMessage()); return ""; } - this.error.cleanError(); return result; } @@ -78,13 +100,23 @@ public String toStringHexa(String base64Text) { * @return String Base64 encoded of stringHexa */ public String fromStringHexaToBase64(String stringHexa) { - byte[] stringBytes = Hex.decode(stringHexa); - String result = new String(Base64.encode(stringBytes)); - if (result == null || result.length() == 0) { - this.error.setError("B64004", "Error encoding base64 from hexa"); + this.error.cleanError(); + byte[] stringBytes; + try { + stringBytes = Hex.decode(stringHexa); + }catch(Exception e) + { + this.error.setError("BS005", e.getMessage()); + return ""; + } + String result = ""; + try { + result = Base64.toBase64String(stringBytes); + }catch(Exception e) + { + this.error.setError("BS006", e.getMessage()); return ""; } - this.error.cleanError(); return result; } } diff --git a/SecurityAPICommons/src/main/java/com/genexus/securityapicommons/encoders/HexaEncoder.java b/SecurityAPICommons/src/main/java/com/genexus/securityapicommons/encoders/HexaEncoder.java index 8ae0148..d65b80e 100644 --- a/SecurityAPICommons/src/main/java/com/genexus/securityapicommons/encoders/HexaEncoder.java +++ b/SecurityAPICommons/src/main/java/com/genexus/securityapicommons/encoders/HexaEncoder.java @@ -24,23 +24,23 @@ public HexaEncoder() { * @return String Hexa hexadecimal representation of plainText */ public String toHexa(String plainText) { + this.error.cleanError(); EncodingUtil eu = new EncodingUtil(); byte[] stringBytes = eu.getBytes(plainText); if (eu.hasError()) { this.error = eu.getError(); return ""; } - StringBuilder sb = new StringBuilder(); - for (byte b : stringBytes) { - sb.append(String.format("%02X ", b)); - } - String result = sb.toString().replaceAll("\\s", ""); - if (result == null || result.length() == 0) { - this.error.setError("HE001", "Error encoding hexa"); + String hexa = ""; + try + { + hexa = Hex.toHexString(stringBytes, 0, stringBytes.length); + }catch(Exception e) + { + this.error.setError("HE001", e.getMessage()); return ""; } - this.error.cleanError(); - return result; + return hexa.toUpperCase(); } /** @@ -50,21 +50,26 @@ public String toHexa(String plainText) { */ public String fromHexa(String stringHexa) { - byte[] resBytes = Hex.decode(stringHexa); + this.error.cleanError(); + byte[] resBytes; + try + { + resBytes = Hex.decode(fixString(stringHexa)); + }catch(Exception e) + { + this.error.setError("HE002", e.getMessage()); + return ""; + } EncodingUtil eu = new EncodingUtil(); String result = eu.getString(resBytes); if (eu.hasError()) { this.error = eu.getError(); return ""; } - if (result == null || result.length() == 0) { - this.error.setError("HE002", "Error decoding hexa"); - return ""; - } - this.error.cleanError(); return result; } + public boolean isHexa(String input) { this.error.cleanError(); @@ -78,7 +83,7 @@ public boolean isHexa(String input) return true; } - private String fixString(String input) + public static String fixString(String input) { if(!input.contains("-")) { @@ -88,5 +93,6 @@ private String fixString(String input) return inputStr; } } + } \ No newline at end of file diff --git a/SecurityAPICommons/src/main/java/com/genexus/securityapicommons/utils/SecurityUtils.java b/SecurityAPICommons/src/main/java/com/genexus/securityapicommons/utils/SecurityUtils.java index a151f49..22dd0b4 100644 --- a/SecurityAPICommons/src/main/java/com/genexus/securityapicommons/utils/SecurityUtils.java +++ b/SecurityAPICommons/src/main/java/com/genexus/securityapicommons/utils/SecurityUtils.java @@ -10,11 +10,10 @@ import java.nio.file.Files; import java.security.KeyFactory; import java.security.NoSuchAlgorithmException; -import com.genexus.securityapicommons.commons.Error; import org.bouncycastle.util.encoders.Hex; -import com.genexus.securityapicommons.commons.SecurityAPIObject; +import com.genexus.securityapicommons.commons.Error; import com.genexus.securityapicommons.config.EncodingUtil; public class SecurityUtils { @@ -27,9 +26,8 @@ public static boolean compareStrings(String one, String two) { } } - - public static byte[] getFileBytes(String pathInput, Error error) - { + + public static byte[] getFileBytes(String pathInput, Error error) { byte[] aux = null; try { File initialFile = new File(pathInput); @@ -39,16 +37,15 @@ public static byte[] getFileBytes(String pathInput, Error error) } return aux; } - - public static InputStream getFileStream(String pathInput, Error error) - { - InputStream aux= null; - try { + + public static InputStream getFileStream(String pathInput, Error error) { + InputStream aux = null; + try { aux = new FileInputStream(new File(pathInput)); } catch (FileNotFoundException e) { error.setError("SU002", e.getMessage()); } - return aux; + return aux; } public static boolean validateExtension(String path, String extension) { @@ -60,8 +57,7 @@ public static boolean validateExtension(String path, String extension) { } /** - * @param path - * path to the file + * @param path path to the file * @return file extension */ public static String getFileExtension(String path) { @@ -74,10 +70,8 @@ public static String getFileExtension(String path) { } /** - * @param path - * path to the file - * @param ext - * extension of the file + * @param path path to the file + * @param ext extension of the file * @return true if the file has the extension */ public static boolean extensionIs(String path, String ext) { @@ -104,18 +98,57 @@ public static final InputStream inputFileToStream(String path) throws IOExceptio final InputStream targetStream = new DataInputStream(new FileInputStream(initialFile)); return targetStream; } - - public static byte[] getHexa(String hex, String code, Error error) - { + + public static byte[] hexaToByte(String hex, Error error) { byte[] output; - try - { + try { output = Hex.decode(hex); - }catch(Exception e) - { - error.setError(code, e.getMessage()); + } catch (Exception e) { + error.setError("SU004", e.getMessage()); return null; } return output; } + + public static InputStream stringToStream(String input, Error error) { + EncodingUtil eu = new EncodingUtil(); + byte[] inputText = eu.getBytes(input); + if (eu.hasError()) { + error = eu.getError(); + return null; + } else { + + try (InputStream inputStream = new ByteArrayInputStream(inputText)) { + return inputStream; + } catch (Exception e) { + error.setError("SU003", e.getMessage()); + } + return null; + } + } + + public static boolean validateStringInput(String name, String value, Error error) + { + if(value == null) + { + error.setError("SU005", String.format("The parameter %s cannot be empty", name)); + return false; + } + if(value.isEmpty()) + { + error.setError("SU006", String.format("The parameter %s cannot be empty", name)); + return false; + } + return true; + } + + public static boolean validateObjectInput(String name, Object value, Error error) + { + if(value == null) + { + error.setError("SU007", String.format("The parameter %a cannot be empty", name)); + return false; + } + return true; + } }