Re: [WebDNA] Best practice re: password storage

This WebDNA talk-list message is from

2013


It keeps the original formatting.
numero = 110792
interpreted = N
texte = --047d7b6d9e1c5caa7604e7df1ca6 Content-Type: text/plain; charset=UTF-8 Dan, Pretty impressive stuff - those functions are great. Is there a reason you decided to use SHA-256 rather than SHA-512? Also on my platform anyway - WebDNA 6.2 on CentOS - I found that there is a stray carriage return when generating a hash using [shell]. So I use the following (the table allows pretty much any character to be used in a password): [table name=prepHash&fields=from,to] $ \$ \ \\ ` \` " \" [/table] [getchars start=1&trim=both][shell]echo -n "[convertwords table=prepHash][the-salt][the-password][/convertwords]" | openssl dgst -sha512[/shell][/getchars] - Tom ============================================== Digital Revolutionaries 1st Floor, Castleriver House 14-15 Parliament Street Temple Bar,Dublin 2 Ireland ---------------------------------------------- [t]: + 353 1 4403907 [e]: [w]: ============================================== On 4 October 2013 00:13, Dan Strong wrote: > I just found a small bug... meant to make the salt 32 chars long not 10, > so it should be [getchars start=1&end=32] in "danFunc_makeSalt". I've > corrected it on my blog. > > -Dan Strong > http://www.DanStrong.com > > > On 10/3/2013 4:11 PM, WebDNA wrote: > >> I hadn't even thought about it until Tom posted the question the other >> day. >> >> Thanks too to Tom for sparking the conversation. >> >> Regards >> >> Stuart Tremain >> IDFK Web Developments >> AUSTRALIA >> webdna@idfk.com.au >> >> >> >> >> On 04/10/2013, at 9:06 AM, Dan Strong wrote: >> >> :-) Happy to help. Let me know if you find any bugs or have a >>> better/smarter way to do it. >>> >>> It actually wasn't that hard (and was fun) to me because I'm interested >>> in it... didn't take too long either once I wrapped my mind around what he >>> was saying. >>> >>> -Dan Strong >>> http://www.DanStrong.com >>> >>> On 10/3/2013 4:03 PM, WebDNA wrote: >>> >>>> THAT'S GREAT DAN, I will have to post you a few more ideas for you to >>>> do the hard work !! >>>> >>>> I will use what you have done for a new site that I am developing. >>>> >>>> Regards >>>> >>>> Stuart Tremain >>>> IDFK Web Developments >>>> AUSTRALIA >>>> webdna@idfk.com.au >>>> >>>> >>>> >>>> >>>> On 04/10/2013, at 9:00 AM, Dan Strong wrote: >>>> >>>> Better formatting here, in case email chews it up: >>>>> http://danstrong.com/blog/**secure-hashing-with-webdna/ >>>>> >>>>> -Dan Strong >>>>> http://www.DanStrong.com >>>>> >>>>> On 10/3/2013 3:59 PM, Dan Strong wrote: >>>>> >>>>>> Using info from the link Stuart sent last night, I cobbled together >>>>>> some functions to do "proper" hashing via WebDNA. If you find any mistakes >>>>>> or have questions let me know. >>>>>> >>>>>> [!]---------------------------**------------------------------** >>>>>> ----------------- >>>>>> One way to do "proper" hashing using WebDNA on linux/unix >>>>>> See: https://crackstation.net/**hashing-security.htm#** >>>>>> properhashing >>>>>> >>>>>> Compact [function]s first, verbose & educational script after. >>>>>> by Dan Strong - http://www.DanStrong.com >>>>>> Free to use, no strings attached. >>>>>> ------------------------------**------------------------------** >>>>>> -------------[/!] >>>>>> >>>>>> [!]------// FUNCTIONS //----------------------------**[/!] >>>>>> [!]-- "danFunc_makeSalt" (ex: "**8630d1f3a3ff0ee8f72856f5692d9c**cd" >>>>>> - usage: "[danFunc_makeSalt]" --[/!] >>>>>> [function name=danFunc_makeSalt] >>>>>> [text]longRandomSalt=[getchars start=1&end=10][encrypt >>>>>> seed=[shell]echo $RANDOM[/shell]&method=**blowfish][shell]echo >>>>>> $RANDOM$RANDOM$RANDOM[/shell][**/encrypt][/getchars][/text] >>>>>> [return][longRandomSalt][/**return] >>>>>> [/function] >>>>>> >>>>>> [!]-- "danFunc_saltHashPassword" (ex: "** >>>>>> e7fdd33de69677f0ed77f68cf54060**ef9fa240204b9c40af0c75d0f80169**bce7" >>>>>> - usage: "[danFunc_saltHashPassword pw=somePassword]" --[/!] >>>>>> [function name=danFunc_saltHashPassword] >>>>>> [text]saltedAndHashed=[shell]**echo -n >>>>>> [danFunc_makeSalt][pw] | sha256sum[/shell][/text] >>>>>> [return][saltedAndHashed][/**return] >>>>>> [/function] >>>>>> >>>>>> >>>>>> [!]------// VERBOSE & EDUCATIONAL //----------------------------** >>>>>> [/!] >>>>>> [text]theUsersPassword=**password-they-provided[/text] >>>>>> >>>>>> [!]=========== TO STORE A PASSWORD ===============[/!] >>>>>> [!]-- 1) Generate a long random salt using a CSPRNG (we're >>>>>> using /dev/random)--[/!] >>>>>> [text]longRandomSalt=[!] >>>>>> [/!][getchars start=1&end=32][!] >>>>>> [/!][encrypt seed=[shell]echo >>>>>> $RANDOM[/shell]&method=**blowfish][!] >>>>>> [/!][shell]echo $RANDOM$RANDOM$RANDOM[/shell][ >>>>>> **!] >>>>>> [/!][/encrypt][!] >>>>>> [/!][/getchars][!] >>>>>> [/!][/text] >>>>>> >>>>>> [!]-- 2) Prepend the salt to the password and hash it with a >>>>>> standard cryptographic hash function such as SHA256 --[/!] >>>>>> [text]saltedAndHashed=[shell]**echo -n [longRandomSalt][* >>>>>> *theUsersPassword] | sha256sum[/shell][/text] >>>>>> >>>>>> [!]-- 3) Save both the salt and the hash in the user's >>>>>> database record -- >>>>>> [append] or [replace] to your db as appropriate >>>>>> salt = [longRandomSalt] >>>>>> hash = [saltedAndHashed] >>>>>> -------------[/!] >>>>>> >>>>>> [!]=========== TO VALIDATE A PASSWORD ===============[/!] >>>>>> [!]-- Test comparison by swapping password variable in STEP >>>>>> 2 to either -SAME or -DIFF --[/!] >>>>>> [text]theUsersPassword-SAME=[**theUsersPassword][/text] >>>>>> [text]theUsersPassword-DIFF=[**random][random][random][/text] >>>>>> >>>>>> [!]-- 1) Retrieve the user's salt and hash from the database >>>>>> -- >>>>>> [search] or [lookup] as approriate >>>>>> - For illustrative purposes, pretend we actually >>>>>> retrieved... >>>>>> - We know these values from above, so we'll set them up >>>>>> now >>>>>> -------------[/!] >>>>>> [text]saltFromDB=[**longRandomSalt][/text] >>>>>> [text]hashFromDB=[**saltedAndHashed][/text] >>>>>> >>>>>> [!]-- 2) Prepend the salt to the given password and hash it >>>>>> using the same hash function --[/!] >>>>>> [text]saltedAndHashedFromDB=[**shell]echo -n >>>>>> [saltFromDB][theUsersPassword-**DIFF] | sha256sum[/shell][/text] >>>>>> >>>>>> [!]-- 3) Compare the hash of the given password with the hash >>>>>> from the database. If they match, the password is correct. Otherwise, the >>>>>> password is incorrect --[/!] >>>>>> [if "[hashfromDB]"="[**saltedAndHashedFromDB]"] >>>>>> [then]THEY MATCH - Let the user in[/then] >>>>>> [else]THEY DON'T MATCH - Release the hounds[/else] >>>>>> [/if] >>>>>> ------------------------------**--------------------------- >>>>>> This message is sent to you because you are subscribed to >>>>>> the mailing list . >>>>>> To unsubscribe, E-mail to: >>>>>> archives: http://mail.webdna.us/list/**talk@webdna.us >>>>>> Bug Reporting: support@webdna.us >>>>>> >>>>> ------------------------------**--------------------------- >>>>> This message is sent to you because you are subscribed to >>>>> the mailing list . >>>>> To unsubscribe, E-mail to: >>>>> archives: http://mail.webdna.us/list/**talk@webdna.us >>>>> Bug Reporting: support@webdna.us >>>>> >>>> ------------------------------**--------------------------- >>>> This message is sent to you because you are subscribed to >>>> the mailing list . >>>> To unsubscribe, E-mail to: >>>> archives: http://mail.webdna.us/list/**talk@webdna.us >>>> Bug Reporting: support@webdna.us >>>> >>> ------------------------------**--------------------------- >>> This message is sent to you because you are subscribed to >>> the mailing list . >>> To unsubscribe, E-mail to: >>> archives: http://mail.webdna.us/list/**talk@webdna.us >>> Bug Reporting: support@webdna.us >>> >> ------------------------------**--------------------------- >> This message is sent to you because you are subscribed to >> the mailing list . >> To unsubscribe, E-mail to: >> archives: http://mail.webdna.us/list/**talk@webdna.us >> Bug Reporting: support@webdna.us >> > > ------------------------------**--------------------------- > This message is sent to you because you are subscribed to > the mailing list . > To unsubscribe, E-mail to: > archives: http://mail.webdna.us/list/**talk@webdna.us > Bug Reporting: support@webdna.us > --047d7b6d9e1c5caa7604e7df1ca6 Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: quoted-printable
Dan,

Pretty impressive stuff - those fu= nctions are great. =C2=A0=C2=A0

Is there a reason = you decided to use SHA-256 rather than SHA-512? =C2=A0 Also on my platform = anyway - WebDNA 6.2 on CentOS - I found that there is a stray carriage retu= rn when generating a hash using [shell]. =C2=A0 So I use the following (the= table allows pretty much any character to be used in a password):


[table name=3DprepHash&fields= =3Dfrom,to]
$\= $
\\\
`\`
"\"
=
[/table]

[getchars start=3D1&trim= =3Dboth][shell]echo -n "[convertwords table=3DprepHash][the-salt][the-= password][/convertwords]" | openssl dgst -sha512[/shell][/getchars]


- Tom

=C2=A0 =C2=A0=C2=A0



=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
Digital Revolutionaries
1st Floor, Castleriver House
14-15 Parliament= Street
Temple Bar,Dublin 2
Ireland
------------------------------= ----------------
[t]: + 353 1 4403907
[e]: <mailto:tom@revolutionaries.ie>=
[w]: <http:= //www.revolutionaries.ie/>
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D


On 4 October 2013 00:13, Dan Strong <da= n@danstrong.com> wrote:
I just found a small bug... meant to make the salt 32 chars long not 10, so= it should be [getchars start=3D1&end=3D32] in "danFunc_makeSalt&q= uot;. I've corrected it on my blog.

-Dan Strong
http://www.DanStrong= .com


On 10/3/2013 4:11 PM, WebDNA wrote:
I hadn't even thought about it until Tom posted the question the other = day.

Thanks too to Tom for sparking the conversation.

Regards

Stuart Tremain
IDFK Web Developments
AUSTRALIA
webdna@idfk.com.au<= /a>




On 04/10/2013, at 9:06 AM, Dan Strong <
dan@danstrong.com> wrote:

:-) Happy to help. Let me know if you find any bugs or have a better/smarte= r way to do it.

It actually wasn't that hard (and was fun) to me because I'm intere= sted in it... didn't take too long either once I wrapped my mind around= what he was saying.

-Dan Strong
http://www.DanStrong= .com

On 10/3/2013 4:03 PM, WebDNA wrote:
THAT'S GREAT DAN, I will have to post you a few more ideas for you to d= o the hard work !!

I will use what you have done for a new site that I am developing.

Regards

Stuart Tremain
IDFK Web Developments
AUSTRALIA
webdna@idfk.com.au<= /a>




On 04/10/2013, at 9:00 AM, Dan Strong <
dan@danstrong.com> wrote:

Better formatting here, in case email chews it up:
http://danstrong.com/blog/secure-hashing-with-webdna/
-Dan Strong
http://www.DanStrong= .com

On 10/3/2013 3:59 PM, Dan Strong wrote:
Using info from the link Stuart sent last night, I cobbled together some fu= nctions to do "proper" hashing via WebDNA. If you find any mistak= es or have questions let me know.

[!]----------------------------------------------------------= ----------------
=C2=A0 =C2=A0 One way to do "proper" hashing using WebDNA on linu= x/unix
=C2=A0 =C2=A0 See: https://crackstation.net/hashing-s= ecurity.htm#properhashing

=C2=A0 =C2=A0 Compact [function]s first, verbose & educational script a= fter.
=C2=A0 =C2=A0 by Dan Strong - http://www.DanStrong.com
=C2=A0 =C2=A0 Free to use, no strings attached.
-------------------------------------------------------------= ------------[/!]

[!]------// FUNCTIONS //----------------------------[/!]
=C2=A0 =C2=A0 [!]-- "danFunc_makeSalt" (ex: "8630d1f3= a3ff0ee8f72856f5692d9ccd" - usage: "[danFunc_makeSalt]&quo= t; --[/!]
=C2=A0 =C2=A0 =C2=A0 =C2=A0 [function name=3DdanFunc_makeSalt]
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 [text]longRandomSalt=3D[getchars = start=3D1&end=3D10][encrypt seed=3D[shell]echo $RANDOM[/shell]&meth= od=3Dblowfish][shell]echo $RANDOM$RANDOM$RANDOM[/shell][/encr= ypt][/getchars][/text]
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 [return][longRandomSalt][/= return]
=C2=A0 =C2=A0 =C2=A0 =C2=A0 [/function]

=C2=A0 =C2=A0 [!]-- "danFunc_saltHashPassword" (ex: "= e7fdd33de69677f0ed77f68cf54060ef9fa240204b9c40af0c75d0f80169b= ce7" - usage: "[danFunc_saltHashPassword pw=3DsomePassword]"= --[/!]
=C2=A0 =C2=A0 =C2=A0 =C2=A0 [function name=3DdanFunc_saltHashPassword]
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 [text]saltedAndHashed=3D[shell]echo -n [danFunc_makeSalt][pw] | sha256sum[/shell][/text]
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 [return][saltedAndHashed][/
return]
=C2=A0 =C2=A0 =C2=A0 =C2=A0 [/function]


[!]------// VERBOSE & EDUCATIONAL //----------------------------= [/!]
=C2=A0 =C2=A0 [text]theUsersPassword=3Dpassword-they-provided[/text]=

=C2=A0 =C2=A0 [!]=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D TO STORE A PASSWORD =3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D[/!]
=C2=A0 =C2=A0 =C2=A0 =C2=A0 [!]-- 1) Generate a long random salt using a CS= PRNG (we're using /dev/random)--[/!]
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 [text]longRandomSalt=3D[!]
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 [/!][getchars start= =3D1&end=3D32][!]
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 [/!][= encrypt seed=3D[shell]echo $RANDOM[/shell]&method=3Dblowfish][!]=
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 [/!][shell]echo $RANDOM$RANDOM$RANDOM[/shell][!]
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 [/!][= /encrypt][!]
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 [/!][/getchars][!]<= br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 [/!][/text]

=C2=A0 =C2=A0 =C2=A0 =C2=A0 [!]-- 2) Prepend the salt to the password and h= ash it with a standard cryptographic hash function such as SHA256 --[/!] =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 [text]saltedAndHashed=3D[shell]
echo -n [longRandomSalt][theUsersPassword] | sha256sum[/shell][= /text]

=C2=A0 =C2=A0 =C2=A0 =C2=A0 [!]-- 3) Save both the salt and the hash in the= user's database record --
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 [append] or [replace] to your db = as appropriate
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 salt =3D [longRando= mSalt]
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 hash =3D [saltedAnd= Hashed]
=C2=A0 =C2=A0 =C2=A0 =C2=A0 -------------[/!]

=C2=A0 =C2=A0 [!]=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D TO VALIDATE A PASSWORD = =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D[/!]
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0[!]-- Test comparison by swapping passwor= d variable in STEP 2 to either -SAME or -DIFF --[/!]
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 [text]theUsersPassword-SAME=3D[theUsersPassword][/text]
[text]theUsersPassword-DIFF=3D[random][random][random][/text]

=C2=A0 =C2=A0 =C2=A0 =C2=A0 [!]-- 1) Retrieve the user's salt and hash = from the database --
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 [search] or [lookup] as approriat= e
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 - For illustrative purposes, pret= end we actually retrieved...
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 - We know these values from above= , so we'll set them up now
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0-------------[/!]
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 [text]saltFromDB=3D[longRa= ndomSalt][/text]
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 [text]hashFromDB=3D[salted= AndHashed][/text]

=C2=A0 =C2=A0 =C2=A0 =C2=A0 [!]-- 2) Prepend the salt to the given password= and hash it using the same hash function --[/!]
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 [text]saltedAndHashedFromDB=3D[shell]echo -n [saltFromDB][theUsersPassword-DIFF] | sha256sum[/= shell][/text]

=C2=A0 =C2=A0 =C2=A0 =C2=A0 [!]-- 3) Compare the hash of the given password= with the hash from the database. If they match, the password is correct. O= therwise, the password is incorrect --[/!]
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 [if "[hashfromDB]"=3D&q= uot;[saltedAndHashedFromDB]"]
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 [then]THEY MATCH - = Let the user in[/then]
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 [else]THEY DON'= T MATCH - Release the hounds[/else]
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 [/if]
---------------------------------------------------------
This message is sent to you because you are subscribed to
the mailing list <ta= lk@webdna.us>.
To unsubscribe, E-mail to: <talk-leave@webdna.us>
archives: http://mail.webdna.us/list/talk@webdna.us
Bug Reporting: suppo= rt@webdna.us
---------------------------------------------------------
This message is sent to you because you are subscribed to
the mailing list <ta= lk@webdna.us>.
To unsubscribe, E-mail to: <talk-leave@webdna.us>
archives: http://mail.webdna.us/list/talk@webdna.us
Bug Reporting: suppo= rt@webdna.us
---------------------------------------------------------
This message is sent to you because you are subscribed to
the mailing list <ta= lk@webdna.us>.
To unsubscribe, E-mail to: <talk-leave@webdna.us>
archives: http://mail.webdna.us/list/talk@webdna.us
Bug Reporting: suppo= rt@webdna.us
---------------------------------------------------------
This message is sent to you because you are subscribed to
the mailing list <ta= lk@webdna.us>.
To unsubscribe, E-mail to: <talk-leave@webdna.us>
archives: http://mail.webdna.us/list/talk@webdna.us
Bug Reporting: suppo= rt@webdna.us
---------------------------------------------------------
This message is sent to you because you are subscribed to
the mailing list <ta= lk@webdna.us>.
To unsubscribe, E-mail to: <talk-leave@webdna.us>
archives: http://mail.webdna.us/list/talk@webdna.us
Bug Reporting: suppo= rt@webdna.us

---------------------------------------------------------
This message is sent to you because you are subscribed to
the mailing list <ta= lk@webdna.us>.
To unsubscribe, E-mail to: <talk-leave@webdna.us>
archives: http://mail.webdna.us/list/talk@webdna.us
Bug Reporting: suppo= rt@webdna.us

--047d7b6d9e1c5caa7604e7df1ca6-- Associated Messages, from the most recent to the oldest:

    
  1. Re: [WebDNA] Best practice re: password storage (Dan Strong 2013)
  2. Re: [WebDNA] Best practice re: password storage (Tom Duke 2013)
  3. Re: [WebDNA] Best practice re: password storage (Dan Strong 2013)
  4. Re: [WebDNA] Best practice re: password storage (WebDNA 2013)
  5. Re: [WebDNA] Best practice re: password storage (Dan Strong 2013)
  6. Re: [WebDNA] Best practice re: password storage (WebDNA 2013)
  7. Re: [WebDNA] Best practice re: password storage (Dan Strong 2013)
  8. Re: [WebDNA] Best practice re: password storage (Dan Strong 2013)
  9. Re: [WebDNA] Best practice re: password storage (WebDNA 2013)
  10. Re: [WebDNA] Best practice re: password storage (Bill DeVaul 2013)
  11. Re: [WebDNA] Best practice re: password storage (Donovan Brooke 2013)
  12. Re: [WebDNA] Best practice re: password storage (Stuart Tremain 2013)
  13. Re: [WebDNA] Best practice re: password storage (Tom Duke 2013)
  14. Re: [WebDNA] Best practice re: password storage (Stuart Tremain 2013)
  15. Re: [WebDNA] Best practice re: password storage (Tom Duke 2013)
  16. Re: [WebDNA] Best practice re: password storage (Dan Strong 2013)
  17. Re: [WebDNA] Best practice re: password storage (Dan Strong 2013)
  18. Re: [WebDNA] Best practice re: password storage (Stuart Tremain 2013)
  19. Re: [WebDNA] Best practice re: password storage (Tom Duke 2013)
  20. Re: [WebDNA] Best practice re: password storage (Dan Strong 2013)
  21. Re: [WebDNA] Best practice re: password storage (Stuart Tremain 2013)
  22. [WebDNA] Best practice re: password storage (Tom Duke 2013)
--047d7b6d9e1c5caa7604e7df1ca6 Content-Type: text/plain; charset=UTF-8 Dan, Pretty impressive stuff - those functions are great. Is there a reason you decided to use SHA-256 rather than SHA-512? Also on my platform anyway - WebDNA 6.2 on CentOS - I found that there is a stray carriage return when generating a hash using [shell]. So I use the following (the table allows pretty much any character to be used in a password): [table name=prepHash&fields=from,to] $ \$ \ \\ ` \` " \" [/table] [getchars start=1&trim=both][shell]echo -n "[convertwords table=prepHash][the-salt][the-password][/convertwords]" | openssl dgst -sha512[/shell][/getchars] - Tom ============================================== Digital Revolutionaries 1st Floor, Castleriver House 14-15 Parliament Street Temple Bar,Dublin 2 Ireland ---------------------------------------------- [t]: + 353 1 4403907 [e]: [w]: ============================================== On 4 October 2013 00:13, Dan Strong wrote: > I just found a small bug... meant to make the salt 32 chars long not 10, > so it should be [getchars start=1&end=32] in "danFunc_makeSalt". I've > corrected it on my blog. > > -Dan Strong > http://www.DanStrong.com > > > On 10/3/2013 4:11 PM, WebDNA wrote: > >> I hadn't even thought about it until Tom posted the question the other >> day. >> >> Thanks too to Tom for sparking the conversation. >> >> Regards >> >> Stuart Tremain >> IDFK Web Developments >> AUSTRALIA >> webdna@idfk.com.au >> >> >> >> >> On 04/10/2013, at 9:06 AM, Dan Strong wrote: >> >> :-) Happy to help. Let me know if you find any bugs or have a >>> better/smarter way to do it. >>> >>> It actually wasn't that hard (and was fun) to me because I'm interested >>> in it... didn't take too long either once I wrapped my mind around what he >>> was saying. >>> >>> -Dan Strong >>> http://www.DanStrong.com >>> >>> On 10/3/2013 4:03 PM, WebDNA wrote: >>> >>>> THAT'S GREAT DAN, I will have to post you a few more ideas for you to >>>> do the hard work !! >>>> >>>> I will use what you have done for a new site that I am developing. >>>> >>>> Regards >>>> >>>> Stuart Tremain >>>> IDFK Web Developments >>>> AUSTRALIA >>>> webdna@idfk.com.au >>>> >>>> >>>> >>>> >>>> On 04/10/2013, at 9:00 AM, Dan Strong wrote: >>>> >>>> Better formatting here, in case email chews it up: >>>>> http://danstrong.com/blog/**secure-hashing-with-webdna/ >>>>> >>>>> -Dan Strong >>>>> http://www.DanStrong.com >>>>> >>>>> On 10/3/2013 3:59 PM, Dan Strong wrote: >>>>> >>>>>> Using info from the link Stuart sent last night, I cobbled together >>>>>> some functions to do "proper" hashing via WebDNA. If you find any mistakes >>>>>> or have questions let me know. >>>>>> >>>>>> [!]---------------------------**------------------------------** >>>>>> ----------------- >>>>>> One way to do "proper" hashing using WebDNA on linux/unix >>>>>> See: https://crackstation.net/**hashing-security.htm#** >>>>>> properhashing >>>>>> >>>>>> Compact [function]s first, verbose & educational script after. >>>>>> by Dan Strong - http://www.DanStrong.com >>>>>> Free to use, no strings attached. >>>>>> ------------------------------**------------------------------** >>>>>> -------------[/!] >>>>>> >>>>>> [!]------// FUNCTIONS //----------------------------**[/!] >>>>>> [!]-- "danFunc_makeSalt" (ex: "**8630d1f3a3ff0ee8f72856f5692d9c**cd" >>>>>> - usage: "[danFunc_makeSalt]" --[/!] >>>>>> [function name=danFunc_makeSalt] >>>>>> [text]longRandomSalt=[getchars start=1&end=10][encrypt >>>>>> seed=[shell]echo $RANDOM[/shell]&method=**blowfish][shell]echo >>>>>> $RANDOM$RANDOM$RANDOM[/shell][**/encrypt][/getchars][/text] >>>>>> [return][longRandomSalt][/**return] >>>>>> [/function] >>>>>> >>>>>> [!]-- "danFunc_saltHashPassword" (ex: "** >>>>>> e7fdd33de69677f0ed77f68cf54060**ef9fa240204b9c40af0c75d0f80169**bce7" >>>>>> - usage: "[danFunc_saltHashPassword pw=somePassword]" --[/!] >>>>>> [function name=danFunc_saltHashPassword] >>>>>> [text]saltedAndHashed=[shell]**echo -n >>>>>> [danFunc_makeSalt][pw] | sha256sum[/shell][/text] >>>>>> [return][saltedAndHashed][/**return] >>>>>> [/function] >>>>>> >>>>>> >>>>>> [!]------// VERBOSE & EDUCATIONAL //----------------------------** >>>>>> [/!] >>>>>> [text]theUsersPassword=**password-they-provided[/text] >>>>>> >>>>>> [!]=========== TO STORE A PASSWORD ===============[/!] >>>>>> [!]-- 1) Generate a long random salt using a CSPRNG (we're >>>>>> using /dev/random)--[/!] >>>>>> [text]longRandomSalt=[!] >>>>>> [/!][getchars start=1&end=32][!] >>>>>> [/!][encrypt seed=[shell]echo >>>>>> $RANDOM[/shell]&method=**blowfish][!] >>>>>> [/!][shell]echo $RANDOM$RANDOM$RANDOM[/shell][ >>>>>> **!] >>>>>> [/!][/encrypt][!] >>>>>> [/!][/getchars][!] >>>>>> [/!][/text] >>>>>> >>>>>> [!]-- 2) Prepend the salt to the password and hash it with a >>>>>> standard cryptographic hash function such as SHA256 --[/!] >>>>>> [text]saltedAndHashed=[shell]**echo -n [longRandomSalt][* >>>>>> *theUsersPassword] | sha256sum[/shell][/text] >>>>>> >>>>>> [!]-- 3) Save both the salt and the hash in the user's >>>>>> database record -- >>>>>> [append] or [replace] to your db as appropriate >>>>>> salt = [longRandomSalt] >>>>>> hash = [saltedAndHashed] >>>>>> -------------[/!] >>>>>> >>>>>> [!]=========== TO VALIDATE A PASSWORD ===============[/!] >>>>>> [!]-- Test comparison by swapping password variable in STEP >>>>>> 2 to either -SAME or -DIFF --[/!] >>>>>> [text]theUsersPassword-SAME=[**theUsersPassword][/text] >>>>>> [text]theUsersPassword-DIFF=[**random][random][random][/text] >>>>>> >>>>>> [!]-- 1) Retrieve the user's salt and hash from the database >>>>>> -- >>>>>> [search] or [lookup] as approriate >>>>>> - For illustrative purposes, pretend we actually >>>>>> retrieved... >>>>>> - We know these values from above, so we'll set them up >>>>>> now >>>>>> -------------[/!] >>>>>> [text]saltFromDB=[**longRandomSalt][/text] >>>>>> [text]hashFromDB=[**saltedAndHashed][/text] >>>>>> >>>>>> [!]-- 2) Prepend the salt to the given password and hash it >>>>>> using the same hash function --[/!] >>>>>> [text]saltedAndHashedFromDB=[**shell]echo -n >>>>>> [saltFromDB][theUsersPassword-**DIFF] | sha256sum[/shell][/text] >>>>>> >>>>>> [!]-- 3) Compare the hash of the given password with the hash >>>>>> from the database. If they match, the password is correct. Otherwise, the >>>>>> password is incorrect --[/!] >>>>>> [if "[hashfromDB]"="[**saltedAndHashedFromDB]"] >>>>>> [then]THEY MATCH - Let the user in[/then] >>>>>> [else]THEY DON'T MATCH - Release the hounds[/else] >>>>>> [/if] >>>>>> ------------------------------**--------------------------- >>>>>> This message is sent to you because you are subscribed to >>>>>> the mailing list . >>>>>> To unsubscribe, E-mail to: >>>>>> archives: http://mail.webdna.us/list/**talk@webdna.us >>>>>> Bug Reporting: support@webdna.us >>>>>> >>>>> ------------------------------**--------------------------- >>>>> This message is sent to you because you are subscribed to >>>>> the mailing list . >>>>> To unsubscribe, E-mail to: >>>>> archives: http://mail.webdna.us/list/**talk@webdna.us >>>>> Bug Reporting: support@webdna.us >>>>> >>>> ------------------------------**--------------------------- >>>> This message is sent to you because you are subscribed to >>>> the mailing list . >>>> To unsubscribe, E-mail to: >>>> archives: http://mail.webdna.us/list/**talk@webdna.us >>>> Bug Reporting: support@webdna.us >>>> >>> ------------------------------**--------------------------- >>> This message is sent to you because you are subscribed to >>> the mailing list . >>> To unsubscribe, E-mail to: >>> archives: http://mail.webdna.us/list/**talk@webdna.us >>> Bug Reporting: support@webdna.us >>> >> ------------------------------**--------------------------- >> This message is sent to you because you are subscribed to >> the mailing list . >> To unsubscribe, E-mail to: >> archives: http://mail.webdna.us/list/**talk@webdna.us >> Bug Reporting: support@webdna.us >> > > ------------------------------**--------------------------- > This message is sent to you because you are subscribed to > the mailing list . > To unsubscribe, E-mail to: > archives: http://mail.webdna.us/list/**talk@webdna.us > Bug Reporting: support@webdna.us > --047d7b6d9e1c5caa7604e7df1ca6 Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: quoted-printable
Dan,

Pretty impressive stuff - those fu= nctions are great. =C2=A0=C2=A0

Is there a reason = you decided to use SHA-256 rather than SHA-512? =C2=A0 Also on my platform = anyway - WebDNA 6.2 on CentOS - I found that there is a stray carriage retu= rn when generating a hash using [shell]. =C2=A0 So I use the following (the= table allows pretty much any character to be used in a password):


[table name=3DprepHash&fields= =3Dfrom,to]
$\= $
\\\
`\`
"\"
=
[/table]

[getchars start=3D1&trim= =3Dboth][shell]echo -n "[convertwords table=3DprepHash][the-salt][the-= password][/convertwords]" | openssl dgst -sha512[/shell][/getchars]


- Tom

=C2=A0 =C2=A0=C2=A0



=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
Digital Revolutionaries
1st Floor, Castleriver House
14-15 Parliament= Street
Temple Bar,Dublin 2
Ireland
------------------------------= ----------------
[t]: + 353 1 4403907
[e]: <mailto:tom@revolutionaries.ie>=
[w]: <http:= //www.revolutionaries.ie/>
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D


On 4 October 2013 00:13, Dan Strong <da= n@danstrong.com> wrote:
I just found a small bug... meant to make the salt 32 chars long not 10, so= it should be [getchars start=3D1&end=3D32] in "danFunc_makeSalt&q= uot;. I've corrected it on my blog.

-Dan Strong
http://www.DanStrong= .com


On 10/3/2013 4:11 PM, WebDNA wrote:
I hadn't even thought about it until Tom posted the question the other = day.

Thanks too to Tom for sparking the conversation.

Regards

Stuart Tremain
IDFK Web Developments
AUSTRALIA
webdna@idfk.com.au<= /a>




On 04/10/2013, at 9:06 AM, Dan Strong <
dan@danstrong.com> wrote:

:-) Happy to help. Let me know if you find any bugs or have a better/smarte= r way to do it.

It actually wasn't that hard (and was fun) to me because I'm intere= sted in it... didn't take too long either once I wrapped my mind around= what he was saying.

-Dan Strong
http://www.DanStrong= .com

On 10/3/2013 4:03 PM, WebDNA wrote:
THAT'S GREAT DAN, I will have to post you a few more ideas for you to d= o the hard work !!

I will use what you have done for a new site that I am developing.

Regards

Stuart Tremain
IDFK Web Developments
AUSTRALIA
webdna@idfk.com.au<= /a>




On 04/10/2013, at 9:00 AM, Dan Strong <
dan@danstrong.com> wrote:

Better formatting here, in case email chews it up:
http://danstrong.com/blog/secure-hashing-with-webdna/
-Dan Strong
http://www.DanStrong= .com

On 10/3/2013 3:59 PM, Dan Strong wrote:
Using info from the link Stuart sent last night, I cobbled together some fu= nctions to do "proper" hashing via WebDNA. If you find any mistak= es or have questions let me know.

[!]----------------------------------------------------------= ----------------
=C2=A0 =C2=A0 One way to do "proper" hashing using WebDNA on linu= x/unix
=C2=A0 =C2=A0 See: https://crackstation.net/hashing-s= ecurity.htm#properhashing

=C2=A0 =C2=A0 Compact [function]s first, verbose & educational script a= fter.
=C2=A0 =C2=A0 by Dan Strong - http://www.DanStrong.com
=C2=A0 =C2=A0 Free to use, no strings attached.
-------------------------------------------------------------= ------------[/!]

[!]------// FUNCTIONS //----------------------------[/!]
=C2=A0 =C2=A0 [!]-- "danFunc_makeSalt" (ex: "8630d1f3= a3ff0ee8f72856f5692d9ccd" - usage: "[danFunc_makeSalt]&quo= t; --[/!]
=C2=A0 =C2=A0 =C2=A0 =C2=A0 [function name=3DdanFunc_makeSalt]
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 [text]longRandomSalt=3D[getchars = start=3D1&end=3D10][encrypt seed=3D[shell]echo $RANDOM[/shell]&meth= od=3Dblowfish][shell]echo $RANDOM$RANDOM$RANDOM[/shell][/encr= ypt][/getchars][/text]
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 [return][longRandomSalt][/= return]
=C2=A0 =C2=A0 =C2=A0 =C2=A0 [/function]

=C2=A0 =C2=A0 [!]-- "danFunc_saltHashPassword" (ex: "= e7fdd33de69677f0ed77f68cf54060ef9fa240204b9c40af0c75d0f80169b= ce7" - usage: "[danFunc_saltHashPassword pw=3DsomePassword]"= --[/!]
=C2=A0 =C2=A0 =C2=A0 =C2=A0 [function name=3DdanFunc_saltHashPassword]
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 [text]saltedAndHashed=3D[shell]echo -n [danFunc_makeSalt][pw] | sha256sum[/shell][/text]
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 [return][saltedAndHashed][/
return]
=C2=A0 =C2=A0 =C2=A0 =C2=A0 [/function]


[!]------// VERBOSE & EDUCATIONAL //----------------------------= [/!]
=C2=A0 =C2=A0 [text]theUsersPassword=3Dpassword-they-provided[/text]=

=C2=A0 =C2=A0 [!]=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D TO STORE A PASSWORD =3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D[/!]
=C2=A0 =C2=A0 =C2=A0 =C2=A0 [!]-- 1) Generate a long random salt using a CS= PRNG (we're using /dev/random)--[/!]
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 [text]longRandomSalt=3D[!]
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 [/!][getchars start= =3D1&end=3D32][!]
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 [/!][= encrypt seed=3D[shell]echo $RANDOM[/shell]&method=3Dblowfish][!]=
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 [/!][shell]echo $RANDOM$RANDOM$RANDOM[/shell][!]
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 [/!][= /encrypt][!]
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 [/!][/getchars][!]<= br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 [/!][/text]

=C2=A0 =C2=A0 =C2=A0 =C2=A0 [!]-- 2) Prepend the salt to the password and h= ash it with a standard cryptographic hash function such as SHA256 --[/!] =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 [text]saltedAndHashed=3D[shell]
echo -n [longRandomSalt][theUsersPassword] | sha256sum[/shell][= /text]

=C2=A0 =C2=A0 =C2=A0 =C2=A0 [!]-- 3) Save both the salt and the hash in the= user's database record --
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 [append] or [replace] to your db = as appropriate
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 salt =3D [longRando= mSalt]
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 hash =3D [saltedAnd= Hashed]
=C2=A0 =C2=A0 =C2=A0 =C2=A0 -------------[/!]

=C2=A0 =C2=A0 [!]=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D TO VALIDATE A PASSWORD = =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D[/!]
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0[!]-- Test comparison by swapping passwor= d variable in STEP 2 to either -SAME or -DIFF --[/!]
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 [text]theUsersPassword-SAME=3D[theUsersPassword][/text]
[text]theUsersPassword-DIFF=3D[random][random][random][/text]

=C2=A0 =C2=A0 =C2=A0 =C2=A0 [!]-- 1) Retrieve the user's salt and hash = from the database --
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 [search] or [lookup] as approriat= e
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 - For illustrative purposes, pret= end we actually retrieved...
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 - We know these values from above= , so we'll set them up now
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0-------------[/!]
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 [text]saltFromDB=3D[longRa= ndomSalt][/text]
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 [text]hashFromDB=3D[salted= AndHashed][/text]

=C2=A0 =C2=A0 =C2=A0 =C2=A0 [!]-- 2) Prepend the salt to the given password= and hash it using the same hash function --[/!]
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 [text]saltedAndHashedFromDB=3D[shell]echo -n [saltFromDB][theUsersPassword-DIFF] | sha256sum[/= shell][/text]

=C2=A0 =C2=A0 =C2=A0 =C2=A0 [!]-- 3) Compare the hash of the given password= with the hash from the database. If they match, the password is correct. O= therwise, the password is incorrect --[/!]
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 [if "[hashfromDB]"=3D&q= uot;[saltedAndHashedFromDB]"]
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 [then]THEY MATCH - = Let the user in[/then]
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 [else]THEY DON'= T MATCH - Release the hounds[/else]
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 [/if]
---------------------------------------------------------
This message is sent to you because you are subscribed to
the mailing list <ta= lk@webdna.us>.
To unsubscribe, E-mail to: <talk-leave@webdna.us>
archives: http://mail.webdna.us/list/talk@webdna.us
Bug Reporting: suppo= rt@webdna.us
---------------------------------------------------------
This message is sent to you because you are subscribed to
the mailing list <ta= lk@webdna.us>.
To unsubscribe, E-mail to: <talk-leave@webdna.us>
archives: http://mail.webdna.us/list/talk@webdna.us
Bug Reporting: suppo= rt@webdna.us
---------------------------------------------------------
This message is sent to you because you are subscribed to
the mailing list <ta= lk@webdna.us>.
To unsubscribe, E-mail to: <talk-leave@webdna.us>
archives: http://mail.webdna.us/list/talk@webdna.us
Bug Reporting: suppo= rt@webdna.us
---------------------------------------------------------
This message is sent to you because you are subscribed to
the mailing list <ta= lk@webdna.us>.
To unsubscribe, E-mail to: <talk-leave@webdna.us>
archives: http://mail.webdna.us/list/talk@webdna.us
Bug Reporting: suppo= rt@webdna.us
---------------------------------------------------------
This message is sent to you because you are subscribed to
the mailing list <ta= lk@webdna.us>.
To unsubscribe, E-mail to: <talk-leave@webdna.us>
archives: http://mail.webdna.us/list/talk@webdna.us
Bug Reporting: suppo= rt@webdna.us

---------------------------------------------------------
This message is sent to you because you are subscribed to
the mailing list <ta= lk@webdna.us>.
To unsubscribe, E-mail to: <talk-leave@webdna.us>
archives: http://mail.webdna.us/list/talk@webdna.us
Bug Reporting: suppo= rt@webdna.us

--047d7b6d9e1c5caa7604e7df1ca6-- Tom Duke

DOWNLOAD WEBDNA NOW!

Top Articles:

Talk List

The WebDNA community talk-list is the best place to get some help: several hundred extremely proficient programmers with an excellent knowledge of WebDNA and an excellent spirit will deliver all the tips and tricks you can imagine...

Related Readings:

[WriteFile] problems (1997) Showing Results Alphabetically in Columns (top to bottom) (2002) expansion domain freak out (2003) sorting problem for sku=0? (1998) Ampersand Searching (2000) encrypt/decrypt password with authenticate (2002) bannerads example idiot (1997) Compressed cookies? (2003) 2nd WebCatalog2 Feature Request (1996) Variable prices and Formulas.db (1997) two unique banners on one page (1997) Multiple adding (1997) WebCat2b12 forgets serial # (1997) webmerch and serials - almost there (1997) Unique SKU Numbers (2000) Emailer setup (1997) remotely add + sign (1997) Setting up WebCatalog with Retail Pro data (1996) show all problem (1997) [WebDNA] OT survey .... (2012)