11package com .laytonsmith .core .functions ;
22
3+ import com .laytonsmith .PureUtilities .Common .ArrayUtils ;
34import com .laytonsmith .PureUtilities .Common .StringUtils ;
45import com .laytonsmith .PureUtilities .Version ;
56import com .laytonsmith .annotations .api ;
910import com .laytonsmith .core .Static ;
1011import com .laytonsmith .core .constructs .CBoolean ;
1112import com .laytonsmith .core .constructs .CByteArray ;
13+ import com .laytonsmith .core .constructs .CSecureString ;
1214import com .laytonsmith .core .constructs .CString ;
1315import com .laytonsmith .core .constructs .Construct ;
1416import com .laytonsmith .core .constructs .Target ;
3638public class Crypto {
3739
3840 public static String docs () {
39- return "Provides common cryptographic functions" ;
41+ return "Provides common cryptographic functions. Many functions in this class are aware of and compatible"
42+ + " with secure_string (where specified in the function documentation). In these cases, if the"
43+ + " argument passed in is a secure_string, it is first decrypted and the underlying string is used"
44+ + " rather than the default string value \" **secure string**\" ." ;
4045 }
4146
4247 private static CString getHMAC (String algorithm , Target t , Construct [] args ) {
4348 try {
4449 SecretKeySpec signingKey = new SecretKeySpec (args [0 ].val ().getBytes (), algorithm );
4550 Mac mac = Mac .getInstance (algorithm );
4651 mac .init (signingKey );
47- byte [] hmac = mac .doFinal (args [1 ]. val (). getBytes ( ));
52+ byte [] hmac = mac .doFinal (getByteArrayFromArg ( args [1 ]));
4853 String hash = StringUtils .toHex (hmac ).toLowerCase ();
4954 return new CString (hash , t );
5055 } catch (NoSuchAlgorithmException | InvalidKeyException ex ) {
5156 throw new CREPluginInternalException ("An error occured while trying to hash your data" , t , ex );
5257 }
5358 }
5459
60+ private static byte [] getByteArrayFromArg (Construct c ) {
61+ byte [] val ;
62+ if (c instanceof CSecureString ) {
63+ val = ArrayUtils .charToBytes (((CSecureString )c ).getDecryptedCharArray ());
64+ } else {
65+ val = c .val ().getBytes ();
66+ }
67+ return val ;
68+ }
69+
5570 @ api
5671 public static class rot13 extends AbstractFunction implements Optimizable {
5772
@@ -144,7 +159,7 @@ public Integer[] numArgs() {
144159 public String docs () {
145160 return "string {val} Returns the md5 hash of the specified string. The md5 hash is no longer considered secure, so you should"
146161 + " not use it for storage of sensitive data, however for general hashing, it is a quick and easy solution. md5 is"
147- + " a one way hashing algorithm." ;
162+ + " a one way hashing algorithm. This function is aware of and compatible with secure_string. " ;
148163 }
149164
150165 @ Override
@@ -170,8 +185,9 @@ public Boolean runAsync() {
170185 @ Override
171186 public Construct exec (Target t , Environment environment , Construct ... args ) throws ConfigRuntimeException {
172187 try {
188+ byte [] val = getByteArrayFromArg (args [0 ]);
173189 MessageDigest digest = java .security .MessageDigest .getInstance ("MD5" );
174- digest .update (args [ 0 ]. val (). getBytes () );
190+ digest .update (val );
175191 String hash = StringUtils .toHex (digest .digest ()).toLowerCase ();
176192 return new CString (hash , t );
177193 } catch (NoSuchAlgorithmException ex ) {
@@ -212,7 +228,8 @@ public Integer[] numArgs() {
212228 public String docs () {
213229 return "string {val} Returns the sha1 hash of the specified string. Note that sha1 is considered more secure than md5,"
214230 + " but is also not considered secure. sha-256 should be used instead for storing sensitive"
215- + " data. It is a one way hashing algorithm." ;
231+ + " data. It is a one way hashing algorithm. This function is aware of and compatible with"
232+ + " secure_string." ;
216233 }
217234
218235 @ Override
@@ -238,8 +255,9 @@ public Boolean runAsync() {
238255 @ Override
239256 public Construct exec (Target t , Environment environment , Construct ... args ) throws ConfigRuntimeException {
240257 try {
258+ byte [] val = getByteArrayFromArg (args [0 ]);
241259 MessageDigest digest = java .security .MessageDigest .getInstance ("SHA1" );
242- digest .update (args [ 0 ]. val (). getBytes () );
260+ digest .update (val );
243261 String hash = StringUtils .toHex (digest .digest ()).toLowerCase ();
244262 return new CString (hash , t );
245263 } catch (NoSuchAlgorithmException ex ) {
@@ -279,7 +297,8 @@ public Integer[] numArgs() {
279297 @ Override
280298 public String docs () {
281299 return "string {val} Returns the sha256 hash of the specified string. Note that sha256 is considered more secure than sha1 and md5, and is"
282- + " typically used when storing sensitive data. It is a one way hashing algorithm." ;
300+ + " typically used when storing sensitive data. It is a one way hashing algorithm. This function"
301+ + " is aware of and compatible with secure_string." ;
283302 }
284303
285304 @ Override
@@ -305,8 +324,9 @@ public Boolean runAsync() {
305324 @ Override
306325 public Construct exec (Target t , Environment environment , Construct ... args ) throws ConfigRuntimeException {
307326 try {
327+ byte [] val = getByteArrayFromArg (args [0 ]);
308328 MessageDigest digest = java .security .MessageDigest .getInstance ("SHA-256" );
309- digest .update (args [ 0 ]. val (). getBytes () );
329+ digest .update (val );
310330 String hash = StringUtils .toHex (digest .digest ()).toLowerCase ();
311331 return new CString (hash , t );
312332 } catch (NoSuchAlgorithmException ex ) {
@@ -348,7 +368,8 @@ public Integer[] numArgs() {
348368 public String docs () {
349369 return "string {val} Returns the sha512 hash of the specified string. Note that sha512"
350370 + " is considered more secure than sha1 and md5 (and sha256, because it takes longer to calculate),"
351- + " and is typically used when storing sensitive data. It is a one way hashing algorithm." ;
371+ + " and is typically used when storing sensitive data. It is a one way hashing algorithm. This"
372+ + " function is aware of and compatible with secure_string." ;
352373 }
353374
354375 @ Override
@@ -374,8 +395,9 @@ public Boolean runAsync() {
374395 @ Override
375396 public Construct exec (Target t , Environment environment , Construct ... args ) throws ConfigRuntimeException {
376397 try {
398+ byte [] val = getByteArrayFromArg (args [0 ]);
377399 MessageDigest digest = java .security .MessageDigest .getInstance ("SHA-512" );
378- digest .update (args [ 0 ]. val (). getBytes () );
400+ digest .update (val );
379401 String hash = StringUtils .toHex (digest .digest ()).toLowerCase ();
380402 return new CString (hash , t );
381403 } catch (NoSuchAlgorithmException ex ) {
@@ -425,7 +447,13 @@ public Construct exec(Target t, Environment environment, Construct... args) thro
425447 log_rounds = Static .getInt32 (args [1 ], t );
426448 }
427449 try {
428- String hash = BCrypt .hashpw (args [0 ].val (), BCrypt .gensalt (log_rounds ));
450+ String val ;
451+ if (args [0 ] instanceof CSecureString ) {
452+ val = new String (((CSecureString )args [0 ]).getDecryptedCharArray ());
453+ } else {
454+ val = args [0 ].val ();
455+ }
456+ String hash = BCrypt .hashpw (val , BCrypt .gensalt (log_rounds ));
429457 return new CString (hash , t );
430458 } catch (IllegalArgumentException ex ) {
431459 throw new CRERangeException (ex .getMessage (), t );
@@ -452,7 +480,8 @@ public String docs() {
452480 + " complete in under a second, however, setting it to 10 will take"
453481 + " many seconds, and setting it to 15 will take a few minutes. The workload must be between 5"
454482 + " and 31. See the documentation for check_bcrypt for full usage. Bcrypt is recommended for"
455- + " password hashing, whereas sha-* functions are not." ;
483+ + " password hashing, whereas sha-* functions are not. This function is aware of and compatible"
484+ + " with secure_string." ;
456485 }
457486
458487 @ Override
@@ -489,7 +518,13 @@ public Boolean runAsync() {
489518
490519 @ Override
491520 public Construct exec (Target t , Environment environment , Construct ... args ) throws ConfigRuntimeException {
492- return CBoolean .get (BCrypt .checkpw (args [0 ].val (), args [1 ].val ()));
521+ String val ;
522+ if (args [0 ] instanceof CSecureString ) {
523+ val = new String (((CSecureString )args [0 ]).getDecryptedCharArray ());
524+ } else {
525+ val = args [0 ].val ();
526+ }
527+ return CBoolean .get (BCrypt .checkpw (val , args [1 ].val ()));
493528 }
494529
495530 @ Override
@@ -510,7 +545,8 @@ public String docs() {
510545 + "string @plain = 'plaintext';\n "
511546 + "string @hash = bcrypt(@plain);\n "
512547 + "msg(if(check_bcrypt(@plain, @hash),"
513- + " 'They match!', 'They do not match!'));\n " ;
548+ + " 'They match!', 'They do not match!'));\n "
549+ + "\n \n This function is aware of and compatible with secure_string." ;
514550 }
515551
516552 @ Override
@@ -653,7 +689,8 @@ public Integer[] numArgs() {
653689
654690 @ Override
655691 public String docs () {
656- return "string {key, val} Returns the md5 HMAC of the specified string using the provided key." ;
692+ return "string {key, val} Returns the md5 HMAC of the specified string using the provided key. This function"
693+ + " is aware of and compatible with secure_string." ;
657694 }
658695
659696 @ Override
@@ -711,7 +748,8 @@ public Integer[] numArgs() {
711748
712749 @ Override
713750 public String docs () {
714- return "string {key, val} Returns the sha1 HMAC of the specified string using the provided key." ;
751+ return "string {key, val} Returns the sha1 HMAC of the specified string using the provided key. This function"
752+ + " is aware of and compatible with secure_string." ;
715753 }
716754
717755 @ Override
@@ -769,7 +807,8 @@ public Integer[] numArgs() {
769807
770808 @ Override
771809 public String docs () {
772- return "string {key, val} Returns the sha256 HMAC of the specified string using the provided key." ;
810+ return "string {key, val} Returns the sha256 HMAC of the specified string using the provided key. This"
811+ + " function is aware of and compatible with secure_string." ;
773812 }
774813
775814 @ Override
0 commit comments