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:

Re:Problem (1997) creating a ShipCosts database (1997) [WebDNA] Cicada - WebDNA_CICADA_6.1.b02 - gratz and request...! (2009) practicing safe queries.. (2000) [WebDNA] Crashing Database (2011) blank page from template (1997) Modulo function? (2000) [WebDNA] Brian Harrington (2019) [WebDNA] Dreamweaver Tag Libraries and Snippets (2011) Using Plug-In while running 1.6.1 (1997) Nested tags count question (1997) [AppendFile] problem (WebCat2b13 Mac .acgi) (1997) search form problem.. (1997) How to redirect based on price subtotal? (1998) OT: P3P (was Shop from PDF) (2004) Document Contains No Data! (1997) WC2.0 Memory Requirements (1997) WebCatalog can't find database (1997) OFF-TOPIC: For Gary Krockover ... (2003) Emailer problem (1998)