Skip to content
This repository

Compare function won't give expected results in all cases #4

Open
wants to merge 1 commit into from

2 participants

Samson Quaye Mohamad El-Husseini
Samson Quaye

The compare function returns -1 if this.password is less than
hashPassword(arguments.password, this.salt), 0 if they are equal and 1
if the first case is reversed. this url shows that

http://help.adobe.com/en_US/ColdFusion/9.0/Developing/WSc3ff6d0ea77859461172e0811cbec09af4-7fd0.html

In Boolean expressions, True, nonzero numbers, and the strings “Yes”,
“1”, “True” are equivalent; and False, 0, and the strings “No”, “0”, and
“False” are equivalent.

Based on this, using the compare won't be the best thing to do.

Samson Quaye snaquaye Problems with the use of the compare function
The compare function returns -1 if this.password is less than
hashPassword(arguments.password, this.salt), 0 if they are equal and 1
if the first case is reversed. this url shows that

http://help.adobe.com/en_US/ColdFusion/9.0/Developing/WSc3ff6d0ea77859461172e0811cbec09af4-7fd0.html

In Boolean expressions, True, nonzero numbers, and the strings “Yes”,
“1”, “True” are equivalent; and False, 0, and the strings “No”, “0”, and
“False” are equivalent.

Based on this, using the compare won't be the best thing to do.
8944c6d
Mohamad El-Husseini
Owner

This is intentional. It's a double negative. We're testing for "if not 0", meaning if the strings don't match, then the password is wrong. So 1, -1, or whatever, does not make a difference. The only time we get a positive match is when the result is 0. We're evaluating for false. -1 and 1 will return true, and we're testing for "not true" or false, hence the "if ! Compare()".

I'm open to merging this if you think it's that important, but I think it's fine the way it is.

Samson Quaye

The reason why i choose the fixed was that implementing that on a project I'm working on refuses authentication even if the password was typed in correctly. If it works fine with you, then the merge won't be necessary.

Thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Showing 1 unique commit by 1 author.

May 28, 2012
Samson Quaye snaquaye Problems with the use of the compare function
The compare function returns -1 if this.password is less than
hashPassword(arguments.password, this.salt), 0 if they are equal and 1
if the first case is reversed. this url shows that

http://help.adobe.com/en_US/ColdFusion/9.0/Developing/WSc3ff6d0ea77859461172e0811cbec09af4-7fd0.html

In Boolean expressions, True, nonzero numbers, and the strings “Yes”,
“1”, “True” are equivalent; and False, 0, and the strings “No”, “0”, and
“False” are equivalent.

Based on this, using the compare won't be the best thing to do.
8944c6d
This page is out of date. Refresh to see the latest.

Showing 1 changed file with 115 additions and 115 deletions. Show diff stats Hide diff stats

  1. +115 115 models/User.cfc
230 models/User.cfc
... ... @@ -1,116 +1,116 @@
1   -component
2   - extends="Model"
3   - hint="Base User model"
4   -{
5   - /*
6   - * @hint Constructor
7   - */
8   - public void function init() {
9   - belongsTo("role");
10   - hasOne(name="passwordToken", modelName="tokenPassword", foreignKey="userId", dependent="delete");
11   - hasOne(name="emailToken", modelName="tokenEmail", foreignKey="userId", dependent="delete");
12   -
13   - beforeSave("sanitize,securePassword,setEmailVerificationOnUpdate");
14   - beforeValidation("setSalt");
15   -
16   - property(name="isConfirmed", default="0");
17   -
18   - validatesConfirmationOf("email,password");
19   - validatesFormatOf(property="email", type="email");
20   - validatesFormatOf(property="password", regEx="^.*(?=.{8,})(?=.*\d)(?=.*[a-z]).*$", message="Your password must be at least 8 characters long and contain a mixture of numbers and letters.");
21   - validatesPresenceOf("name,email,password");
22   - validatesUniquenessOf("email");
23   - }
24   -
25   - // --------------------------------------------------
26   - // Callbacks
27   -
28   - /*
29   - * @hint Sanitizes the user object.
30   - */
31   - private void function sanitize() {
32   - this.name = HtmlEditFormat(this.name);
33   - }
34   -
35   - /*
36   - * @hint Secures the password property before saving it.
37   - */
38   - private void function securePassword() {
39   - if ( StructKeyExists(this, "passwordConfirmation") ) {
40   - this.password = hashPassword(this.password, this.salt);
41   - }
42   - }
43   -
44   - /*
45   - * @hint Initiates email verification process on e-mail update.
46   - * @note Reverts the email to its original value until the new address is verified.
47   - */
48   - private void function setEmailVerificationOnUpdate() {
49   - if ( ! this.isNew() && this.hasChanged("email") ) {
50   - this.emailToken = this.emailToken();
51   -
52   - if ( IsObject(this.emailToken) ) {
53   - this.emailToken.update(generateTokenValue(this.email));
54   - }
55   - else {
56   - this.emailToken = this.createEmailToken(generateTokenValue(this.email));
57   - }
58   - this.email = this.changedFrom("email");
59   - }
60   - }
61   -
62   - /**
63   - * @hint Sets the salt property for the password.
64   - */
65   - private void function setSalt() {
66   - if ( StructKeyExists(this, "passwordConfirmation") ) {
67   - this.salt = GenerateSecretKey("AES", 256);
68   - }
69   - }
70   -
71   - // --------------------------------------------------
72   - // Public
73   -
74   - /**
75   - * @hint Authenticates a user object.
76   - */
77   - public boolean function authenticate(required string password) {
78   - return ! Compare(this.password, hashPassword(arguments.password, this.salt));
79   - }
80   -
81   - /**
82   - * @hint Generates a token.
83   - * @pendingValue Holds a temporary value; an update email address that's pending verification, for example.
84   - * @validForInHours The number of days this token is valid for.
85   - */
86   - public struct function generateTokenValue(string pendingValue="", numeric validForInHours=24) {
87   - var token = {
88   - expires = DateAdd("h", arguments.validForInHours, Now()),
89   - pendingValue = arguments.pendingValue,
90   - value = Rereplace(CreateUUID(), "-", "", "all")
91   - };
92   - return token;
93   - }
94   -
95   - /*
96   - * @hint Convenience method to blank user password.
97   - */
98   - public void function passwordToBlank() {
99   - if ( StructKeyExists(this, "password") ) this.password = "";
100   - if ( StructKeyExists(this, "passwordConfirmation") ) this.passwordConfirmation = "";
101   - }
102   -
103   - // --------------------------------------------------
104   - // Private
105   -
106   - /*
107   - * @hint Hashes a password string.
108   - */
109   - private string function hashPassword(required string password, required string salt) {
110   - for (var i = 1; i <= 1024; i++) {
111   - arguments.password = Hash(arguments.password & arguments.salt, "SHA-512");
112   - }
113   - return arguments.password;
114   - }
115   -
  1 +component
  2 + extends="Model"
  3 + hint="Base User model"
  4 +{
  5 + /*
  6 + * @hint Constructor
  7 + */
  8 + public void function init() {
  9 + belongsTo("role");
  10 + hasOne(name="passwordToken", modelName="tokenPassword", foreignKey="userId", dependent="delete");
  11 + hasOne(name="emailToken", modelName="tokenEmail", foreignKey="userId", dependent="delete");
  12 +
  13 + beforeSave("sanitize,securePassword,setEmailVerificationOnUpdate");
  14 + beforeValidation("setSalt");
  15 +
  16 + property(name="isConfirmed", default="0");
  17 +
  18 + validatesConfirmationOf("email,password");
  19 + validatesFormatOf(property="email", type="email");
  20 + validatesFormatOf(property="password", regEx="^.*(?=.{8,})(?=.*\d)(?=.*[a-z]).*$", message="Your password must be at least 8 characters long and contain a mixture of numbers and letters.");
  21 + validatesPresenceOf("name,email,password");
  22 + validatesUniquenessOf("email");
  23 + }
  24 +
  25 + // --------------------------------------------------
  26 + // Callbacks
  27 +
  28 + /*
  29 + * @hint Sanitizes the user object.
  30 + */
  31 + private void function sanitize() {
  32 + this.name = HtmlEditFormat(this.name);
  33 + }
  34 +
  35 + /*
  36 + * @hint Secures the password property before saving it.
  37 + */
  38 + private void function securePassword() {
  39 + if ( StructKeyExists(this, "passwordConfirmation") ) {
  40 + this.password = hashPassword(this.password, this.salt);
  41 + }
  42 + }
  43 +
  44 + /*
  45 + * @hint Initiates email verification process on e-mail update.
  46 + * @note Reverts the email to its original value until the new address is verified.
  47 + */
  48 + private void function setEmailVerificationOnUpdate() {
  49 + if ( ! this.isNew() && this.hasChanged("email") ) {
  50 + this.emailToken = this.emailToken();
  51 +
  52 + if ( IsObject(this.emailToken) ) {
  53 + this.emailToken.update(generateTokenValue(this.email));
  54 + }
  55 + else {
  56 + this.emailToken = this.createEmailToken(generateTokenValue(this.email));
  57 + }
  58 + this.email = this.changedFrom("email");
  59 + }
  60 + }
  61 +
  62 + /**
  63 + * @hint Sets the salt property for the password.
  64 + */
  65 + private void function setSalt() {
  66 + if ( StructKeyExists(this, "passwordConfirmation") ) {
  67 + this.salt = GenerateSecretKey("AES", 256);
  68 + }
  69 + }
  70 +
  71 + // --------------------------------------------------
  72 + // Public
  73 +
  74 + /**
  75 + * @hint Authenticates a user object.
  76 + */
  77 + public boolean function authenticate(required string password) {
  78 + return this.password == hashPassword(arguments.password, this.salt) ? true : false;
  79 + }
  80 +
  81 + /**
  82 + * @hint Generates a token.
  83 + * @pendingValue Holds a temporary value; an update email address that's pending verification, for example.
  84 + * @validForInHours The number of days this token is valid for.
  85 + */
  86 + public struct function generateTokenValue(string pendingValue="", numeric validForInHours=24) {
  87 + var token = {
  88 + expires = DateAdd("h", arguments.validForInHours, Now()),
  89 + pendingValue = arguments.pendingValue,
  90 + value = Rereplace(CreateUUID(), "-", "", "all")
  91 + };
  92 + return token;
  93 + }
  94 +
  95 + /*
  96 + * @hint Convenience method to blank user password.
  97 + */
  98 + public void function passwordToBlank() {
  99 + if ( StructKeyExists(this, "password") ) this.password = "";
  100 + if ( StructKeyExists(this, "passwordConfirmation") ) this.passwordConfirmation = "";
  101 + }
  102 +
  103 + // --------------------------------------------------
  104 + // Private
  105 +
  106 + /*
  107 + * @hint Hashes a password string.
  108 + */
  109 + private string function hashPassword(required string password, required string salt) {
  110 + for (var i = 1; i <= 1024; i++) {
  111 + arguments.password = Hash(arguments.password & arguments.salt, "SHA-512");
  112 + }
  113 + return arguments.password;
  114 + }
  115 +
116 116 }

Tip: You can add notes to lines in a file. Hover to the left of a line to make a note

Something went wrong with that request. Please try again.