TheSwamp
Code Red => AutoLISP (Vanilla / Visual) => Topic started by: jsr on July 16, 2010, 06:55:40 AM
-
Hi everybody
If someone writes auto/visual lisp code for commercial use. What are the possible measures to prevent its piracy. When using .NET we can have installation packages/activation codes etc But for lisp code what are the possibilities. Even if we create a .fas file it makes the code unreadable but still it can be easily copied/used etc.
Please guide.
-
Actually Lisp easier to protect than .NET : ) compile to .vlx, or .fas,
Get the OS activation code or motherboard serial and go from there
-
Thanks eAmbiguousOutput
Would you please explain bit more. I want to give the .fas/vlx applications to others who are authorized to use but do not want them to further distribute them to others.
Thanks again.
-
heres a link to where you can get some of the hardware needed to build a key
http://www.theswamp.org/index.php?topic=29556.msg350816#msg350816
-
Thanks eAmbiguousOutput
Would you please explain bit more. I want to give the .fas/vlx applications to others who are authorized to use but do not want them to further distribute them to others.
Thanks again.
Step 1. create a lisp routine in your VLX that can collect a few serials from the hardware.
Step 2, create a lisp routine in your VLX that can code and decode the serials.
Step 3, create a lisp routine that can generate a request key and accept an activation key.
step 4, store the activation key.
step 5, at various points in your lisp routine I.e at launch, check that activation key exists and is valid.
something like that :laugh:
-
Is the application already written? If not I wouldn't worry about piracy, it's more important to write the application.
Sorry to be harsh again, but keying your software to the OS or some piece of hardware is, hold it - here's that word again --, stupid. Unless people absolutely need your software, which they probably don't, then that is a first class ticket to no sales.
-
One thing that has puzzled me actually is that surely you need the program to modify itself in some way, else what is to stop the user running the program on another system and the program just going through the procedure as if it was the first time launch?
-
Dont be stupid If you do not have any reasonable answer do not bark like street dogs. Non sence
-
Dont be stupid If you do not have any reasonable answer do not bark like street dogs. Non sence
whoa junior ... you may just need to explain that !!
who are you talking to and why are you being so aggressive ..
-
Paul's got one of those opinions :lol:
I have one program on the market that has keying, While this had absolutely no affect on sales, it is a real PIA to deal with.
-
One thing that has puzzled me actually is that surely you need the program to modify itself in some way, else what is to stop the user running the program on another system and the program just going through the procedure as if it was the first time launch?
There's lots of ways to handle it. Self modifying code could be one. But if you want to key on the hardware then some sort of hardware hash needs to be sent company so they can send you a key based on it and your name or something.
-
Paul's got one of those opinions :lol:
I have one program on the market that has keying, While this had absolutely no affect on sales, it is a real PIA to deal with.
I did give a warning. :-D :-D
-
Aladdin had support for Autolisp, if your looking for a commercial solution http://www.aladdin.com/support/hasp/hasp4/legacyapi.aspx
-
Sorry Its for Mr. pkohut who should not reply if he does not have a reasonable answer.
I think no question is non snece If the purpose is to learn something. One cannot learn if he/she does not ask questions whether reasonable or not. I had a question in my mind so I posted it to forum Now one does not need to worry if I have any application that is valuable for other or not.
Thanks.
-
Dont be stupid If you do not have any reasonable answer do not bark like street dogs. Non sence
Sorry I didn't provide you with the answer you wanted to hear. After rereading what I wrote, I must agree with myself 100%. Again, my apologies.
-
One thing that has puzzled me actually is that surely you need the program to modify itself in some way, else what is to stop the user running the program on another system and the program just going through the procedure as if it was the first time launch?
There's lots of ways to handle it. Self modifying code could be one. But if you want to key on the hardware then some sort of hardware hash needs to be sent company so they can send you a key based on it and your name or something.
I see - thanks Paul :-)
-
I wrote an app for an office once. I thought it worked well under my limited knowledge, the office receiving it thought it was perfect, but I'm sure the guru's here would laugh at the code - I sure do after looking back at it.
But, my point I want to throw out here is this;
I didn't know how to protect it very well and was sure it would be copied and spread across the world in one way or another, so I put a one year limit on it. I told the office receiving it that there was a one year limit and if they needed it again, just to call for it.
During that time, the code was updated here and there and sent to them with the original date still intact. The office called once and I simply updated the code for the next year, created a VLX and sent it to them. There is nothing in the code referencing me. When the time is up, it simply comes back with a statement: "Program needs to be updated". So if anyone else has it, they either need to go back to the office they got it from to get an update, or call me if they know it's from me.
But I wasn't trying to get sales, so there was no need for advertising.
Well, anyway, my too sence wirth. :)
-
I've done that before - when attempting to sell a few programs I've offered a "7-day trial" before in a compiled VLX, but I've never gone into the realms of adding any sort of 'key' (my software isn't really expensive enough for that I shouldn't think).
-
Sorry Its for Mr. pkohut who should not reply if he does not have a reasonable answer.
I think no question is non snece If the purpose is to learn something. One cannot learn if he/she does not ask questions whether reasonable or not. I had a question in my mind so I posted it to forum Now one does not need to worry if I have any application that is valuable for other or not.
Thanks.
A professional developer giving his professional advice/opinion.
BTW, Don't be so cranky, this forum already has a token a55h0l3--and that would be me-. You play nice now or I will be forced to critique your question asking abilities. And before you come off your chair or froth at the mouth, That was a joke; calm down or I will be forced to reach through the internet and slap you.
Ah but it does matter if the program is `valuable or not' and eAmbiguousOutpt gave you another reason--more like a formula if you will--besides the `sales' he said that he has one app out there that is causing him problems. The PITA is relative to the popularity of the app.
Build a key/hidden file/widget into the installer?
Dont be stupid If you do not have any reasonable answer do not bark like street dogs. Non sence
Sorry I didn't provide you with the answer you wanted to hear. After rereading what I wrote, I must agree with myself 100%. Again, my apologies.
Now that was funny.
-
Doh! I did the yearly update thing too! Now that was stupid (on my part) : ) I had a ton of expiring builds while I was moving from the US to HK.. I remember sitting in the airport making builds.
IMO there is nothing wrong with keying your applications, In fact it can be a great learning experience that leads to other paths, I.e. encryption etc. Reading the white paper on how Microsoft attaches to hardware serials and gives each a weight, (you can replace two or three hardware items without killing the key), was very interesting. I spent two years writing a converter from Acad to a third party software called Pattern Systems. PS sells for $35,000 for three seats, I sold the converter for $800. Sales were going fantastic until PS started to go belly up.. Whatever, I made a bit of cash. I believe the keying helped me make more, as I dealt with companies that were growing, they had to call me when they needed more seats.
-
Sorry I didn't provide you with the answer you wanted to hear. After rereading what I wrote, I must agree with myself 100%. Again, my apologies.
Now that was funny.
got my boots on :lol:
-
It makes sense to me to key an AutoCAD add-on (LISP, .NET, ARX) to an AutoCAD license rather than the hardware.
This seems easy enough to do with a stand-alone ACAD license, but network licenses appear to be another story.
Comments?
-
Do you mean using something like the _PKSER Sys Var?
-
Do you mean using something like the _PKSER Sys Var?
Yes, or ..
(can't at this moment lay hands on proper information in HKEY_LOCAL_MACHINE->SOFTWARE)
-
Here are the routines I setup for an office when I was cad manager. Back when I thought it was really important to protect the offices investment in custom routines (read my own ego about them). After I left the new cad manager called me about how to remove all of that.
The concept was that an encrypted serial # was stored in the registry after a password was entered into each station's config box. Used doslib to get MAC address. Had options for master unexpiring password with network install, or year long passwords for install on roaming machines. Each of my separate .lsp files had this in the header. Entire project compiled into one VLX.
;;; Authorization check
(if (or (not BCV_Authorization)
(not (= "abracadabra" (BCV_Authorization "CAVEman")))
)
(progn (alert "\nBCV Routines not authorized!\nQuitting.")(exit))
)
Code ran on v2004, I'm sure it is missing some global subroutines from other files. No promises that it works, but might be useful for learning or cribbing code (as I did). Hope my old comments are self explanatory enough.
(code post split into 2 parts)
Dan
Main routines:
;;;==========================================================
;;; ABC_Cypher.lsp
;;; Requires doslib.arx to be loaded
;;;
;;; Establishes authorization of ABC routines
;;; At first time setup of ABC routines, this file calls a dialog
;;; with password for authorization "CAVEman"
;;; Assuming success, the routines are authorized with with encrypted
;;; registry entry unique to each machine (can't be copied)
;;;
;;; If password is incorrect, the file aborts loading of all further ABC routines
;;;==========================================================
(if ABCdebug (princ "\nStarting ABC_Cypher.lsp"))
;;; test for required dos_lib
(if (not (and dos_version
(setq dosv (dos_version))
(>= 6 (atoi dosv))
) ;_and
) ;_not
(progn (alert "\nRequires DOSLIB utilities!\nQuitting ABC Routines")(exit))
)
;;;==========================================================
;;; Function : Returns only a part of a list, works like SUBSTR
;;; Argument : [ Lst ] - List to check
;;; [ Start] - starting position, starts from 1
;;; [ len ] - Number of elements to extract
;;; If len is negative, returns until the end of the list
;;; Return : The extracted list
;;; Updated : December18, 1998
;;; Copyright: (C) 2000, Four Dimension Technologies, Singapore
;;; Contact : rakesh.rao@4d-technologies.com for help/support/info
;;;==========================================================
(defun ABC_SubList (Lst Start len / _len n m _Lst)
(if (minusp len)
(setq len 999999999)
) ;_ if
(setq _len (length Lst)
n (min (- Start 1) _len) ; Starting Index
m (min (+ n len) _len) ; Ending Index
_Lst '()
) ;_ setq
(while (< n m)
(setq _Lst (cons (nth n Lst) _Lst)
n (1+ n)
) ;_ setq
) ;_ while
(reverse _Lst)
) ;_ defun
;;;=========================================================================
;;; function to return a repeated string of x length characters
;;; if x is less than string length, returns shorter version
;;;=========================================================================
(defun ABC_RepeatStringLen (str x / i newstr)
(setq i 1
newstr ""
) ;_ setq
(while (< (strlen newstr) x)
(setq newstr (strcat newstr (substr str i 1))
i (1+ i)
) ;_ setq
(if (> i (strlen str))
(setq i 1)
) ;_ if
) ;_ while
newstr
) ;_ defun
;;;=========================================================================
;;; simple shift up of one decimal number by another on a base of 255 (hexidecimal)
;;; used for simple encoding of one number by another
;;;=========================================================================
(defun ABC_IntShiftBaseUp (a b base / c)
(setq c (+ a b))
(if (> c base)
(setq c (- c base))
c
)
)
;;;=========================================================================
;;; simple shift down of one decimal number by another on a base of 255 (hexidecimal)
;;; used for simple decoding of one number by another
;;;=========================================================================
(defun ABC_IntShiftBaseDown (a b base / c)
(setq c (- a b))
(if (< c 0)
(setq c (+ c base))
c
)
)
;|
;;;=========================================================================
;;; encrypt a string with MAC Address
;;; used to make authorization unique to machine
;;;=========================================================================
(defun ABC_EncryptStr_Local (str / StrListDec MACAddress MACListDec NewListDec NewStr)
(if (dos_macaddress)
(progn
(setq StrListDec (vl-string->list str) ;convert string to list of ascii codes
MACAddress (dos_strremove (dos_macaddress) ":") ;remove colons from MAC Address
MACAddress (ABC_RepeatStringLen MACAddress (strlen str)) ;repeat MACAddress length of string to be encrypted
MACListDec (vl-string->list MACAddress) ;convert MACAddress to list of ascii codes
;; cypher string with macaddress
NewListDec (mapcar '(lambda (x y) (ABC_IntShiftBaseUp x y 255)) StrListDec MACListDec)
NewStr (vl-list->string NewListDec) ;convert cyphered codes back to ascii
)
)
)
)
;;;=========================================================================
;;; Decrypt a string with MAC Address
;;;=========================================================================
(defun ABC_DecryptStr_Local (str / StrListDec MACAddress MACListDec NewListDec NewStr)
(if (dos_macaddress)
(progn
(setq StrListDec (vl-string->list str) ;convert string to list of ascii codes
MACAddress (dos_strremove (dos_macaddress) ":") ;remove colons from MAC Address
MACAddress (ABC_RepeatStringLen MACAddress (strlen str)) ;repeat MACAddress length of string to be encrypted
MACListDec (vl-string->list MACAddress) ;convert MACAddress to list of ascii codes
;; cypher string with macaddress
NewListDec (mapcar '(lambda (x y) (ABC_IntShiftBaseDown x y 255)) StrListDec MACListDec)
NewStr (vl-list->string NewListDec) ;convert cyphered codes back to ascii
)
)
)
)
|;
;;;=========================================================================
;;; ALTERNATIVE
;;; encrypt a string with computer name
;;; used to make authorization unique to machine
;;;=========================================================================
(defun ABC_EncryptStr_Local (str / StrListDec computer_name MACListDec NewListDec NewStr)
(if (dos_computer)
(progn
(setq StrListDec (vl-string->list str) ;convert string to list of ascii codes
computer_name (dos_computer)
computer_name (ABC_RepeatStringLen computer_name (strlen str)) ;repeat computer_name length of string to be encrypted
MACListDec (vl-string->list computer_name) ;convert computer_name to list of ascii codes
;; cypher string with computer name
NewListDec (mapcar '(lambda (x y) (ABC_IntShiftBaseUp x y 255)) StrListDec MACListDec)
NewStr (vl-list->string NewListDec) ;convert cyphered codes back to ascii
)
)
)
)
;;;=========================================================================
;;; ALTERNATIVE
;;; Decrypt a string with computer name
;;;=========================================================================
(defun ABC_DecryptStr_Local (str / StrListDec MACAddress MACListDec NewListDec NewStr)
(if (dos_computer)
(progn
(setq StrListDec (vl-string->list str) ;convert string to list of ascii codes
computer_name (dos_computer)
computer_name (ABC_RepeatStringLen computer_name (strlen str)) ;repeat computer_name length of string to be encrypted
MACListDec (vl-string->list computer_name) ;convert MACAddress to list of ascii codes
;; cypher string with computer_name
NewListDec (mapcar '(lambda (x y) (ABC_IntShiftBaseDown x y 255)) StrListDec MACListDec)
NewStr (vl-list->string NewListDec) ;convert cyphered codes back to ascii
)
)
)
)
;;;=========================================================================
;;; Encrypt a string with a base 255 ABC Cypher (defined below)
;;;=========================================================================
(defun ABC_EncryptStr255 (str / StrListDec CypherCode NewListDec NewStr)
(if *ABC-Cypher255*
(progn
(setq StrListDec (vl-string->list str) ;convert string to list of ascii codes
CypherCode (ABC_SubList (*ABC-Cypher255* "CAVEman") 1 (strlen str)) ;get cypher in length of string to be encoded
;; cypher string
NewListDec (mapcar '(lambda (x y) (ABC_IntShiftBaseUp x y 255)) StrListDec CypherCode)
NewStr (vl-list->string NewListDec) ;convert cyphered codes back to ascii
)
)
)
)
;;;=========================================================================
;;; Decrypt a string with a base 255 ABC Cypher
;;;=========================================================================
(defun ABC_DecryptStr255 (str / StrListDec CypherCode NewListDec NewStr)
(if *ABC-Cypher255*
(progn
(setq StrListDec (vl-string->list str) ;convert string to list of ascii codes
CypherCode (ABC_SubList (*ABC-Cypher255* "CAVEman") 1 (strlen str)) ;get cypher in length of string to be encoded
;; cypher string
NewListDec (mapcar '(lambda (x y) (ABC_IntShiftBaseDown x y 255)) StrListDec CypherCode)
NewStr (vl-list->string NewListDec) ;convert cyphered codes back to ascii
)
)
)
)
;;;=========================================================================
;;; 1000 character long cypher - base 255
;;; Cypher definition needs to be protected from listing
;;; Use (*ABC-Cypher255* "CAVEman") to return list
;;; Be sure to declare as local
;;;=========================================================================
(defun *ABC-Cypher255* (password)
(if (= password "CAVEman")
(list 229 178 59 199 34 102 136 2 206 210 137 100 25 210 210 93 129 221 32 89 136
7 228 152 226 34 231 47 204 212 130 180 208 2 116 178 161 97 187 141 78 128
105 209 130 50 1 166 10 165 50 98 88 253 146 227 64 209 38 198 151 100 77
19 7 228 2 108 178 150 217 107 244 70 206 50 241 195 60 213 35 215 23 171
172 125 194 38 155 185 144 65 222 237 86 43 26 246 19 53 31 244 38 164 54
17 251 134 247 33 187 16 233 111 232 179 154 146 99 102 118 162 217 92 253 166
256 161 175 145 177 199 74 161 60 58 160 136 16 68 188 34 16 119 143 33 153
109 210 127 186 159 105 14 136 74 233 1 9 13 137 197 185 85 48 254 12 36
217 9 2 93 2 211 34 31 97 90 246 73 154 193 103 199 40 57 255 183 47
168 133 4 125 90 227 136 98 161 227 84 159 171 158 56 33 120 50 23 195 61
162 43 210 9 95 201 123 21 121 200 243 123 223 16 124 210 192 129 13 90 97
178 200 58 137 181 10 143 216 103 50 166 24 114 240 68 242 139 69 74 5 23
244 148 222 180 143 99 181 219 242 47 129 31 66 63 65 43 71 206 5 13 65
43 173 242 3 148 197 234 129 61 142 184 133 68 156 105 213 254 4 166 109 96
151 116 19 246 27 107 248 33 2 255 155 22 139 251 179 84 215 185 63 6 213
55 148 20 142 163 134 75 194 109 113 101 75 129 89 86 69 187 214 174 110 44
6 109 182 81 61 25 127 198 169 120 115 152 165 197 130 205 241 170 224 50 136
235 162 15 73 13 196 219 50 210 66 123 93 235 9 51 122 172 106 213 2 30
219 87 214 81 154 74 128 52 38 109 214 220 244 223 50 129 118 4 245 34 206
203 147 5 56 85 215 17 160 164 164 57 85 102 220 232 85 115 177 185 49 18
21 84 245 169 121 209 16 229 160 107 187 242 181 231 206 229 93 131 127 230 256
195 2 50 3 244 133 155 29 193 123 136 153 173 175 30 157 211 32 165 76 178
10 191 231 116 47 138 170 118 189 72 161 112 221 159 48 22 88 15 116 139 82
179 76 117 133 231 51 21 10 229 170 53 19 249 101 74 150 97 244 149 105 112
40 168 182 7 225 40 83 15 125 17 221 236 177 115 48 165 233 220 13 188 3
105 134 94 130 189 22 256 11 194 233 249 80 143 56 64 42 57 80 214 25 3
29 4 227 167 196 239 134 40 62 185 55 251 107 165 170 215 156 116 86 25 251
121 233 254 227 148 184 148 134 153 63 200 233 69 150 71 171 87 231 175 138 228
192 208 36 125 99 95 233 67 211 238 183 124 223 135 17 199 208 186 128 128 256
129 240 113 20 195 167 102 3 222 183 190 175 5 104 140 70 207 155 106 26 203
137 134 51 117 244 21 79 100 35 175 131 6 185 193 64 194 210 156 230 219 97
61 172 240 73 114 9 93 36 96 90 116 58 22 255 202 148 49 170 131 171 64
9 231 164 232 149 35 160 114 183 134 256 210 249 29 46 196 119 244 207 18 89
227 231 158 118 64 212 72 239 65 172 71 233 109 233 15 38 253 218 88 181 116
223 99 110 83 215 18 116 56 193 230 118 76 7 140 224 74 108 252 193 254 20
205 146 151 150 215 157 160 163 183 52 244 37 82 124 142 94 225 253 134 244 185
169 27 104 69 160 17 239 106 94 83 38 214 142 30 148 90 63 147 117 241 163
11 207 117 45 2 51 178 36 242 60 225 127 242 48 37 47 120 197 38 154 19
128 92 124 114 161 43 229 149 35 93 136 120 178 28 33 31 30 250 23 72 69
44 34 172 223 130 33 24 49 58 228 69 20 82 21 187 86 82 3 156 216 76
128 176 124 15 145 136 63 40 24 13 145 224 78 93 74 166 30 69 74 44 63
44 49 162 39 218 33 81 163 217 21 8 67 227 178 141 78 27 16 164 133 123
125 186 91 80 160 216 233 7 4 245 72 64 122 48 154 102 74 35 105 179 182
208 156 247 177 78 193 237 96 203 208 137 59 239 57 8 103 85 91 35 39 11
53 51 235 214 112 175 241 56 143 200 236 221 116 136 176 131 235 75 88 244 134
225 216 46 109 64 127 79 103 16 85 88 211 238 218 102 191 191 12 123 233 240
66 97 199 239 187 210 101 186 121 110 75 232 54 157 23 236 28 246 22 3 7
65 133 145 242 172 184 85 108 76 226 59 154 131
) ;_ list
)
) ;_ setq
;;; desired encryption ascii 32 (space) through 126 = 94
;;;=========================================================================
;;; 500 character long cypher - base 36
;;; Cypher definition needs to be protected from listing
;;; Use (*ABC-Cypher36* "CAVEman") to return list
;;; Be sure to declare as local
;;;=========================================================================
(defun *ABC-Cypher36* (password)
(if (= password "CAVEman")
(list 29 24 31 1 7 34 14 6 6 0 15 35 23 19 30 3 22 26 2 17 8 24 26 20 18 26
5 18 5 9 5 14 28 5 15 19 6 31 27 9 21 13 10 34 9 22 20 23 12 33 9 6
1 2 0 14 4 8 34 28 7 29 29 11 17 6 8 20 24 6 23 19 23 26 33 8 31 17
24 27 4 8 30 10 14 19 6 19 17 22 7 18 13 27 22 8 26 24 11 18 22 7 5 34
1 34 26 34 27 19 13 9 25 22 33 35 14 30 22 34 24 12 33 3 22 13 19 18 8 26
30 9 6 1 34 19 9 0 12 27 23 31 11 1 26 12 24 30 12 12 11 22 24 1 8 12
11 21 1 15 19 24 3 7 31 15 13 7 24 9 12 27 18 11 30 32 21 31 16 35 35 6
31 16 10 21 11 23 4 3 9 12 0 3 15 5 23 30 10 31 19 3 18 18 24 14 32 21
23 29 21 35 13 6 16 13 3 3 16 28 1 10 33 17 31 26 7 13 25 19 6 16 31 10
23 1 32 15 33 33 1 2 22 30 33 34 31 9 22 31 1 0 17 11 11 3 7 21 1 24
22 14 5 28 22 26 26 30 6 12 3 21 25 28 3 3 14 27 17 33 6 16 19 4 4 35
12 14 31 32 18 10 12 3 29 24 17 20 26 34 32 30 1 9 19 8 25 23 30 22 8 7
34 21 20 9 1 31 17 20 24 2 13 31 3 34 17 33 2 6 30 27 28 14 2 22 6 34
7 0 27 8 25 29 32 8 25 5 22 9 29 26 7 26 14 23 19 3 0 11 28 3 7 7
33 2 2 10 5 26 16 1 31 1 2 21 33 21 29 33 21 5 0 35 32 29 19 7 20 11
29 20 35 6 5 23 25 27 17 31 28 19 14 4 11 8 1 6 25 2 23 7 2 8 13 16
1 11 27 25 18 4 34 12 25 13 3 34 32 1 15 32 13 19 3 2 21 23 34 9 29 9
8 1 16 34 27 5 26 22 6 24 35 27 3 12 33 35 18 15 22 6 19 34 31 7 25 9
17 33 27 18 21 1 20 1 19 16 21 3 34 7 35 6 0 6 15 7 17 14 35 31 10 7
2 18 8 3 16 14
) ;_ list
)
) ;_ defun
-
Second half of code.
;;;==========================================================
;;; Make password dialog box on the fly in temp folder
;;;==========================================================
(defun ABC_MakeTempDcl (/ file)
(setq file (open (strcat (getenv "TEMP") "\\" "~getpass.dcl") "w"))
(write-line "// GETPASS.DCL" file)
(write-line "//" file)
(write-line "passdlg : dialog {" file)
(write-line " label = \"Password to Authorize ABC Routines\";" file)
(write-line " : row {" file)
(write-line " : radio_column {" file)
(write-line " : radio_button {" file)
(write-line " key = \"network\";" file)
(write-line " label = \"Network Installation\";" file)
(write-line " }" file)
(write-line " : radio_button {" file)
(write-line " key = \"offsite\";" file)
(write-line " label = \"Offsite Installation\";" file)
(write-line " }" file)
(write-line " } //column" file)
(write-line " } //end :row" file)
(write-line " : edit_box {" file)
(write-line " label = \"Password:\";" file)
(write-line " edit_width = 20;" file)
(write-line " key = \"password\";" file)
(write-line " password_char = \"*\";" file)
(write-line " is_default = true;" file)
(write-line " }" file)
(write-line " ok_cancel;" file)
(write-line "}" file)
(close file)
)
;;;==========================================================
;;; Dialog to bring up options for authorization
;;; with password, intended for first time set up of
;;; AutoCAD only, dialog should be skipped after that
;;;==========================================================
(defun ABC_GETPASS (/ dcl_id pass auth return)
(ABC_MakeTempDcl)
(setq auth "network") ;set default
(setq dcl_id (load_dialog (strcat (getenv "TEMP") "\\" "~getpass.dcl")))
(if (new_dialog "passdlg" dcl_id)
(progn (set_tile "network" "1")
(action_tile "network" "(setq auth \"network\")")
(action_tile "offsite" "(setq auth \"offsite\")")
(action_tile "password" "(setq pass $value)")
(mode_tile "password" 2) ; set focus
(start_dialog)
(unload_dialog dcl_id)
) ;_ progn
(princ "Error: Unable to load GETPASS.DCL. ")
) ;_ if
;;(if (setq file (findfile "~getpass.dcl"))(vl-file-delete file))
;; Authorize ABC routines with encrypted registry code
(cond ((and (= "network" auth)(= "CAVEman" pass))
(ABC_Authorize "CAVEman" "Full Network Permissions")
(setq return T) ;return flag for success
)
;; for offsite, if password date range and current date match
;; authorize routines with encrypted code & password
((and (= "offsite" auth)(ABC_AuthCheckOffsite pass))
(ABC_Authorize "CAVEman" (strcat "Temporary Offsite Permissions:" pass))
(setq return T) ;return flag for success
)
) ;_ cond
return
) ;_ defun
;;;==========================================================
;;; Check for ABC Routines authorized with encrypted registry entry
;;; Decodes with local (MAC Address) code & also ABC cypher to ensure
;;; that registry entry is unique to each machine (can't be copied)
;;; Returns string type of authorization or nil for failure
;;;==========================================================
(defun ABC_AuthorizationCheck (/ auth dosv dauth return cpos ofpass)
(and (setq dosv (dos_version)) ;verify doslib version
(>= 6 (atoi dosv))
;; get encrypted authorizationcode
(setq auth (dos_regget "HKEY_LOCAL_MACHINE\\Software\\ABC" "AuthCode")) ;get auth code from registry
;; decrypt code
(setq dauth (ABC_DecryptStr_local (ABC_DecryptStr255 auth))) ;decrypt it
(or (if (= dauth "Full Network Permissions") ;if it is network
(setq return "Network") ;return network permission
) ;_ if
(and (setq cpos (vl-string-position 58 dauth)) ;or offsite - look for colon separating offsite password
(setq ofpass (substr dauth (+ 2 cpos))) ;with password after colon
(if (ABC_AuthCheckOffsite ofpass) ;verify with offsite list
(setq return "Offsite") ;return offsite permission
) ;_ if
) ;_ and
) ;_ or
) ;_ and
return
) ;_ defun
;;;==========================================================
;;; Verify offsite password with date list and current date
;;; returns T for good
;;; returns nil for invalid password
;;; alerts for for valid out of date password,and returns nil
;;;==========================================================
(defun ABC_AuthCheckOffsite (pass / pwdlst pdatelst stdate enddate cdate newestini inidate return)
;;; association list of offsite passwords with range of valid dates
(setq pwdlst ;ABC_OffsitePasswordList
(list (list "aardwolves" (list 20030701 20031231))
(list "test" (list 20030926 20030927))
(list "gelatinize" (list 20040101 20040631))
(list "lutestring" (list 20040701 20041231))
(list "rottweiler" (list 20050101 20050631))
(list "picaresque" (list 20050701 20051231))
(list "flugelhorn" (list 20060101 20060631))
(list "beleaguers" (list 20060701 20061231))
(list "zymologies" (list 20070101 20070631))
(list "nonathlete" (list 20070701 20071231))
(list "martensite" (list 20080101 20080631))
(list "firstlings" (list 20080701 20081231))
) ;_ list
) ;_ setq
(if (setq pdatelst (assoc pass pwdlst)) ;if password is in list
(progn
(setq stdate (caadr pdatelst) ;get start date
enddate (cadadr pdatelst) ;get end date
cdate (getvar "cdate") ;get current date
;; get newest ini file in the windows directory
newestini (car (dos_dir (strcat (dos_windir) "*.ini") 4))
;; get date of file
inidate (ABC_getfiledate (strcat (dos_windir) newestini))
)
(if (and (< stdate cdate enddate) ;if current date is in range
(< inidate (+ cdate 0.01)) ; and current date is older than newest ini file
; (adjusted an hour ahead to deal with daylight savings
)
(progn
(setq return T) ; set return flag ok
;; (> 3 (- 20030927 (getvar "cdate")))
(if (and (> 3 (- enddate cdate)) ;if expires in less than three days
(not (vl-bb-ref '*ABCExpireWarn*)) ;check session flag if user already warned
) ;_and
(progn
(alert (strcat "Note: ABC Routines about to expire!" ;warn
"\n\nContact ABC Architects for new password."
) ;_strcat
) ;_alert
(vl-bb-set '*ABCExpireWarn* T) ;set session flag that user has been warned
) ;_progn
) ;_if
) ;_progn
(progn
(alert "Password has expired - quitting") ; else warn expired
(dos_regset "HKEY_LOCAL_MACHINE\\Software\\ABC" "AuthCode" "") ;clear code
)
) ;_if
) ;_progn
) ;_if
return
) ;_defun
;;;==========================================================
;;; Authorizes ABC routines
;;; with encrypted registry entry
;;;==========================================================
(defun ABC_Authorize (password authd / auth)
(if (= "CAVEman" password)
(progn (setq auth (ABC_EncryptStr255 (ABC_EncryptStr_local authd))
) ;_ setq
(dos_regset "HKEY_LOCAL_MACHINE\\Software\\ABC" "AuthCode" auth)
) ;_ progn
) ;_ if
) ;_ defun
;;;==========================================================
;;; Actions to run when ABC_Cypher.lsp is loaded
;;;==========================================================
;;; Check if routines authorized
(if (not (ABC_AuthorizationCheck))
;; Not authorized, bring up dialog for password & authorization
;; if dialog unsuccessful, then abort
(if (not (ABC_GetPass))
(progn (alert "\nIncorrect password!\nQuitting ABC Routines.")
;; probably paranoid, but on failure,
;; clear all encryption routines from memory
(setq ABC_SubList nil
ABC_SubList nil
ABC_RepeatStringLen nil
ABC_IntShiftBaseUp nil
ABC_IntShiftBaseDown nil
ABC_EncryptStr_Local nil
ABC_DecryptStr_Local nil
ABC_EncryptStr255 nil
ABC_DecryptStr255 nil
*ABC-Cypher255* nil
*ABC-Cypher36* nil
ABC_MakeTempDcl nil
ABC_GETPASS nil
ABC_AuthorizationCheck nil
ABC_AuthorizeNetwork nil
ABC_Authorizeoffsite nil
ABC_AuthCheckOffsite nil
ABC_OffsitePasswordList nil
) ;_ setq
(exit)
) ;_ progn
) ;_ if
) ;_ if
;;;==========================================================
;;; define shortform authorization for other routines to check
;;; just returns "abracadabra" for authorized, else nil
;;; other checks for type of authorization must use ABC_AuthorizationCheck
;;;==========================================================
(defun ABC_Authorization (password)(if (= password "CAVEman") "abracadabra"))
(if ABCdebug (princ "\nFinished ABC_Cypher.lsp"))
(princ)
;;;==========================================================
;;;==========================================================
;;;==========================================================
;;;==========================================================
;;;==========================================================
;;; Development work and source info below
;|
(defun test ()
(setq t1 (ABC_EncryptStr255 "All good dogs go to heaven, 1908234, (*!@!@(*&"))
(setq t1dec (vl-string->list t1))
(setq t2 (ABC_DecryptStr255 t1))
(setq t2dec (vl-string->list t2))
)
(defun c:t1 ()
(setq t1 (getstring "\nText to encode: "))
(setenv "ABC\\Test" (ABC_EncryptStr255 t1))
(princ)
)
(defun c:t2 ()
(princ (ABC_DecryptStr255 (getenv "ABC\\Test")))
)
(defun c:t3 ()
(setq t1 (getstring "\nText to encode: "))
(setenv "ABC\\Test" (ABC_EncryptStr255 (ABC_EncryptStr255_mac t1)))
(princ)
)
(defun c:t4 ()
(princ (ABC_DecryptStr255_mac (ABC_DecryptStr255 (getenv "ABC\\Test"))))
)
;;; convert date to list of ascii characters
(setq t1 (vl-string->list (menucmd "M=$(edtime, $(getvar, date),YYMODD)")))
;(48 51 48 57 48 57)
;;; convert numbers to hex?
;(mapcar '(lambda(x) (atoi (std-num->hex x))) (vl-string->list (menucmd "M=$(edtime, $(getvar, date),YYMODD)")))
;(30 33 30 39 30 38)
;;; get semi unique computer id - network address number
;(dos_macaddress)
;"00:01:02:C7:70:28"
;;; convert to list &
;;; convert hex to decimal
(setq t2 (mapcar '(lambda(x) (std-hex->num x)) (dos_strtokens (dos_macaddress) ":" T)))
;(0 16 181 250 88 249)
;; test encrypt date (t1) with MACAddress (t2)
(setq t3 (mapcar '(lambda (x y) (ABC_IntShiftBaseUp x y 255)) t1 t2))
;(48 67 229 52 136 51)
;; test decryption of date (reverse)
(setq t4 (mapcar '(lambda (x y) (ABC_IntShiftBaseDown x y 255)) t3 t2))
;(48 51 48 57 48 57)
|;
;|
;;; From: rurban@sbox.tu-graz.ac.at (rurban@sbox.tu-graz.ac.at)
;;; Subject: Re: Need Encryption Algorythm in AutoLisp
;;; Newsgroups: autodesk.autocad.customization
;;; Date: 1998/08/23
;;;
;;; the trick is using a VERY long cypher which is not transported together with
;;; the encrypted string.
;;;
;;; how to splice a char of 255 states into a char of 36 states?
;;; this could be possible with some heavy compression techniques (huffmann or lzw
;;; for example) but if it works for every string is not guaranteed and cannot be
;;; generally guaranteed.
;;;
;;; 3) if we assume that the string to be encrypted is of the same order as
;;; the resulting string (36 valid chars) it is very easy and unbreakable by
;;; generating a long sequence of random characters and encryptr your string
;;; with the random cypher-string as generator. xor is enough. and use a simple
;;; alphabet to map the result onto the valid charset.
;;;
;;; Strings to be encrypted must be alpha-numberic, no spaces or symbols
;; generate the cypher, this should be quite long and not
;; transported together with with the code!
(defun init-cypher (len / s i)
(setq *cypher* nil)
(setq *encypher-pos* 0)
(setq *decypher-pos* 0)
(setq *cypher-len* len)
(repeat len
(setq *cypher* (cons (ABC_random 36) *cypher*)))
)
;;; map the decrypted char [0-9],[A-Z] to int 65-101,
;;; force uppercase,
;;; result is guaranteed to be in [65-101]
(defun enmap-char (c / i)
(setq i (ascii c))
(if (<= 97 i 122) (setq i (- i 32))) ; force upcase
(if (<= 48 i 57) (setq i (+ i 43))) ; 0-9 above Z
(+ 65 (rem (abs (- i 65)) 36)) ; force interval 65-101
)
;;; map the encrypted int 65-101 to [0-9],[A-Z]
;;; result is a one-char string in [0-9][A-Z]
(defun demap-char (i)
(chr (cond ((<= 65 i 90) i)
((> i 90) (- i 43)))
))
(defun encrypt-string (s / i l crypt)
(setq l (strlen s)
i 1
crypt ""
) ;_ setq
(while (<= i l)
(setq crypt (strcat crypt
(demap-char
(encypher-fun
(enmap-char (substr s i 1))
(nth *encypher-pos* *cypher*)
) ;_ encypher-fun
) ;_ demap-char
) ;_ strcat
i (1+ i)
*encypher-pos* (rem (1+ *encypher-pos*) *cypher-len*)
) ;_ setq
) ;_ while
crypt
) ;_ defun
(defun decrypt-string (s / i l crypt)
(setq l (strlen s)
i 1
crypt ""
) ;_ setq
(while (<= i l)
(setq crypt (strcat crypt
(demap-char
(decypher-fun
(enmap-char (substr s i 1))
(nth *decypher-pos* *cypher*)
) ;_ decypher-fun
) ;_ demap-char
) ;_ strcat
i (1+ i)
*decypher-pos* (rem (1+ *decypher-pos*) *cypher-len*)
) ;_ setq
) ;_ while
crypt
) ;_ defun
;; use simple shifting by the cypher:
; x: 65-101, y: 0-35 => 65-101
; (ENCYPHER-FUN 78 33) => 75
(defun encypher-fun (x y)
(+ 65 (rem (+ (- x 65) y) 36)))
; x: 65-101, y: 0-35 => 65-101
; (DECYPHER-FUN 75 33) => 78 ??
(defun decypher-fun (x y)
(while (< (- x y) 65)
(setq x (+ x 36)))
(- x y))
(defun cyphertest ()
(init-cypher 1000)
(setq s1 "einkleinenachtmusik123")
(setq s2 "undnocheine987")
(print s1)(princ " => ")
(princ (setq es1 (encrypt-string s1)))
(print s2)(princ " => ")
(princ (setq es2 (encrypt-string s2)))
(print (decrypt-string es1))
(print (decrypt-string es2))
(prin1)
)
|;
;|
"einkleinenachtmusik123" => N95PPUZGQUOBK9BQ1JTQOI
"undnocheine987" => 1VZTEZHNXPNZC6
"EINKLEINENACHTMUSIK123"
"UNDNOCHEINE987"
|;
-
FWIW,
vl-registry-read
vl-registry-write
appear to work just fine.
Docs say:
You cannot use vl-registry-write for HKEY_USERS or KEY_LOCAL_MACHINE
But this is evidently not so. I have written to HKEY_LOCAL_MACHINE\\Software\\My Stuff, & read back the value.
So, I see no need to load doslib to perform this one task.
-
have a few years, successfully using the keys Senselock EL-STD (http://www.senselock.com/Senselockel.asp)