Invalid Signature

I had my extension signed and then I installed it under Sketchup 2017. The extension manager initially showed my extension as signed. I then took a directory list under the DOS command prompt: Dir . /s > dir.txt.

Then I ran my extension which modified a txt file and created a license.dat file and a couple more txt files. I looked at the extension manager and it said signed. Then I restarted sketchup and looked at the extension manager and it said invalid signature.

I then shut down sketchup and replaced the first modified txt file with the original one from the rbz package and then started up sketchup and again looked at the extension manager. Now it said signed.

It appears that you can add as many files to the extension and they donā€™t affect signing.

Do you have a question ?

You seem not to understand that the package submitted for signing, is signed in the state it is when submitted.

Any later change to any of those files, will trigger an alert that an invalid change to one of the signed files has happened. It is the whole point of signing, after all.

So, if you need to be making changes to any configuration files at runtime, then they should not be included with the package when you submit it for signing.

My initial understanding was based on what Tig wrote in a Sketchucation post suggesting that txt files would be ignored. My testing showed that not to be quite correct.

http://sketchucation.com/forums/viewtopic.php?t=66202#p607908

For now my extensions are going to be unsigned. I see no point in spending time reworking and moving files outside of my plugin folder. First of all this would cause many of my users grief. It would also make the installation more difficult as I would have 2 installers for each plugin.

Perhaps Iā€™ll consider compressing all of editable text files that I supply. Then on startup I could then decompress them into various folders if they donā€™t already exist. That way the original compressed file wouldnā€™t change. At least this way I could keep it to a single install.

No. I did not say that. I said they should not be included when signing.

They can be written into the folder later. Or donā€™t use the ā€œ.txtā€ extension. or perhaps a sub-folder?

(Since they came out with this signing stuff, Iā€™ve avoided doing anything with the EW. Waiting till the ā€œkinks are ironed out.ā€)

What we seem to need is a ā€œ.ignoreā€ file like Git uses.

Let me ping @ChrisFullmer, so you can get an answer ā€œstraight from the horseā€™s mouth.ā€

The best solution I can come up with is to create my own virtual store within my plugin folder. What I am contemplating is to have empty template folders within the store (I name the store folder ā€˜storageā€™).

My routines look for the template under storage so when looking for a rule I check first if it is in gkware_cabmaker\storage\rul and if not then look where it is for older versions which was gkware_camaker\rul

This strategy solves several potential issues:

  1. It allows the signature to stay valid.
  2. if users want to modify the supplied templates and they donā€™t or wonā€™t rename the template then it wonā€™t get overwritten during the next update.

And no Dan - I never said that you said ā€¦
And also no - I donā€™t have a question - Iā€™m simply trying to share my observations.

1 Like

Iā€™ve apparently run into this problem also.
(My extensions are encrypted and signed automatically on their way to being tested by Trimble, who publishes them on the EW. Therefore, I never need to download the result. Which also means that I canā€™t easily test the result.)
In the last release of one of my extensions I added a one character txt file (either ā€œyā€ or ā€œnā€) to record the user response this dialog which displays on initial load:
image
This reminder has eliminated countless support emails from customers too lazy to look at the help file after doing an update.
BUT it seems that my ruby code that writes ā€œnā€ to the txt file invalidates the extension signature!!! Who knew?

None of the SU or SU API documentation mentions the ā€œinvalid signatureā€ status or explains how it might occur and what its implications are for the ā€œloading policy modesā€.
I know I might have used the OS registry to do this, but wanted to avoid the untestable multiversion can of worms that this might entail.

Is there another file type other that txt that the signature process ignores?
Any other suggestions???

def check_2dxy
  Sketchup.read_default('2DXY', 'SiteSurveyTools')
end

def write_2dxy(reply)
  Sketchup.write_default('2DXY', 'SiteSurveyTools', reply)
end

# run on first run to set the default
if check_2dxy == nil
  write_2dxy('y')
end

# in your dialog return code if changed by user
  write_2dxy('n')

should work for all versions since v6ā€¦

john

The Extension Warehouse could certainly be more transparent towards developers. A lot of problems seem to stem from this, e.g. the struggles Iā€™ve had figuring out how licensing works.

However Iā€™ve moved away from saving files in the extension directory. In some situations the user doesnā€™t even have write permission to this directory, e.g. when an extension is installed in the program folder to be shared between users.

I would use an approach similar to what John shows, but use Booleans rather than strings.

anything gets converted to strings when using Sketchup.write_default, so you may as well use stringsā€¦

Sketchup.read_default will only return strings on a macā€¦

check your .json pref files to see if thatā€™s the same on PCā€¦

john

The official list of file-types which get hashed in the signing process is supposed to beā€¦
RB [after encryption RBS/RBE], JS, CSS, HTM, HTML - because these can be changed and affect how an extension works.
The TXT file extension was originally excluded, but, for some [as yet unexplained], itā€™s now included in the signing process, so if your tool ships with a .TXT file itā€™s signed, and any changes to that file will break the validity of the signing.
At the moment file extensions like LOG, DAT, LIC etc seem to be ignored so you could try using one of those.

As explained above - Set/Get a setting using write_default/read_default is the simple way to save these values externallyā€¦

These set/get values are global and will apply to your tool when run in that SketchUp version, for any model.

If you want to set/get values on a model by model basis then set up a attribute attached directly to the model itself. This can then be accessed using get/set for each model, with defaults used if not already set upā€¦

Your best [simplest] approach is probably not to ship [or at least sign] the RBZ with the TXT file in it, it can be created later and not affect the signing.

Of course the ā€œpowers that beā€ might make a decision to sign ALL files in the submitted RBZ and return an error should other files be found in that signed Extensionā€™s subfolder !
Of course, this would be a major step, and would very likely disaffect many developers.
However, the initial, then ā€˜the enhancedā€™, signing process still arrived, despite considerable opposition from many developers [behind the scenes], and frankly itā€™s still without any real measurable benefit to users, or us developers !

Alternatively tell your users to set their Extension Loading Policy to be Unrestricted [at least for now]ā€¦

I tried to say that ~ a year ago ā€¦

ā€¦

:roll_eyes:

I hate SketchUp for Mac -_- . When using Windows there are no indications whatsoever that other types wouldnā€™t be supported.

Iā€™ve tested on Windows (SU 2017). Booleans, Strings, Integers and Floats are supported. Symbols on the other hand seem to be executed when read o.0 .

Sketchup.write_default("test", "test", :symbol)
Sketchup.read_default("test", "test")
=> Error: #<NameError: undefined local variable or method `symbol' for main:Object>

Or

Sketchup.write_default("test", "test", :Sketchup)
Sketchup.read_default("test", "test").class
=> Class

This code perhaps be used for code injections

Sketchup.write_default("test", "test", :"Sketchup.active_model.entities.clear!")
Sketchup.read_default("test", "test") # Deletes all instances in the model root.

Now Iā€™m getting tired.

YES! Finally someone gets it. Iā€™ve been saying this for years.
In fact I said it here 2 days ago ā€¦

Everything read back is passed into eval() to reproduce the original object.

ā€¦ and yes it was very unsafe ! Why else do you think theyā€™ve switched to JSON parsed strings ?

Much much safer !

1 Like

JSON makes no difference, that code still deletes all entities when you call
Sketchup.read_default("test", "test")ā€¦

it is stored without the symbol on macā€¦

        "test": {
            "test": "Sketchup.active_model.entities.clear!"
        },

john

It makes a difference if ā€œsomeoneā€ would not program such unsafe things.

I was just reading in the Chrome Extension tutorial how we should not eval JSON strings, ā€¦ and should parse them instead.

Ruby has the same JSON.parse() method JavaScript has (except JS creates a JS Object, whereas Ruby creates a Hash object.)

ie ā€¦ at SketchUpā€™s Ruby console ā€¦

json = '{ "test" : "Sketchup.active_model.entities.clear!" }'
hash = JSON.parse(json)
# model entities are STILL there !
hash.inspect
#=> {"test"=>"Sketchup.active_model.entities.clear!"}
1 Like

With a little luck it should be possible to refactor read_default to parse the registry entry properly, while still being backward compatible.

Just a note to say the ā€œsomeoneā€ was not aimed at you John. It was aimed at whomever had the ā€œbrilliantā€ idea to eval storage values in the first place.

Yes, but it would still be backwardly dangerous, ā€¦ unless they patched old versions. (Which is unlikely to officially happen.)

It may be left for a third party patch to do.

I was just thinking about how to parse numeric strings (integers, floats, scientific notation, etc.) into the proper kind of Ruby numeric. Not much problem with some of the SketchUp API types as they call #inspect upon them before storage, ie: "Point3d(1.0,2.0,1.0)"

Iā€™ve been thinking quite a lot about storing Lengths and other SU classes to JSON/file and parse it back to the original format again. I havenā€™t made any progress in that.

However I donā€™t think Point3ds and other advanced types are really needed in the registry, at least not for now. I almost only have stored Booleans and sometimes string identifiers for user settings using write_defaults. In the future it could perhaps be nice to have support for all SU types but to start with I think itā€™s most important to fix the security issue for newer SU versions.

Something similar to JSON.load could be used to read and #to_json could be used to write. Some special handling would be required when Ruby and JSON donā€™t match, e.g. nil vs null. Iā€™m not sure if mayor versions can read and write to the same locations. If not there is no compatibility to maintain anyway.

For other readers it is trivial to store Ruby types in hashes and convert back and forth to and from JSON.

See example ā€¦ (in another thread.)

Not a problem, see:

JSON::Ext::Generator::GeneratorMethods::NilClass

nil.to_json.inspect
#=> "null"

jstore = {:val => nil}.to_json
jstore.inspect
#=> "{\"val\":null}"

hash = JSON.parse(jstore,symbolize_names:true)
hash.inspect
#=> {:val=>nil}

When we say ā€œregistryā€ we now mean ā€œstorageā€ because most of extension storage has moved to JSON files, rather than the registry. (Native dialog sizes and positions are likely still in the registry.)

It would be nice to have parity between Attribute Dictionaries and JSON storage.

This means that the JSON library may need to be extended with a few API specific class generator methods. Not difficult because many have conversion methods to array and/or hash which are already JSON compatible.

The tricky part si to convert back to SketchUp classes. What in a JSON file could tell that a float is to be interpreted as a Length? Or an Array should be interpreted as a Vector3d? Youā€™s have to extend the JSON specification along with rewriting a generator/parser to cater for these types.