Coder Social home page Coder Social logo

konstantinpavlikhin / watchdog Goto Github PK

View Code? Open in Web Editor NEW
46.0 3.0 7.0 2.12 MB

Simple registration framework for OS X apps. DSA/ECDSA support. No OpenSSL required.

License: MIT License

Ruby 2.73% Objective-C 97.27%
serials registration trial shareware activation ecdsa serialkey macos

watchdog's Introduction

Watchdog

Watchdog is a simple registration framework for OS X apps.

Watchdog features

  • Drop-in component for application registration. Watchdog has clear API, trivial to install to your project.
  • No heavyweight dependancies — framework doesn't rely on ugly OpenSSL library and uses modern Security.framework APIs.
  • Watchdog utilizes robust and secure industry standart DSA/ECDSA signature algorithms.
  • Watchdog seamlessly supports both DSA and ECDSA serials — just set an appropriate public key.

What Watchdog is not

Watchdog has nothing to do with with trial periods or evaluation launches count. It's up to you to implement an appropriate TrialController with behavior specific to your domain. There are numerous ways you can implement a trial. For example, some applications allow limited time of an unrestricted app usage, some allow limited number of launches in trial mode, some just restrict feature set and so on... There is no possibility (an need) to abstract this stuff into Watchdog.

Adding Watchdog to your project

  1. Add Watchdog to your project as a submodule.
$ cd ~/Development/Application
$ git submodule add https://github.com/konstantinpavlikhin/Watchdog.git
$ git submodule update --init --recursive
  1. Setup a dependency between your project and Watchdog
  • Find Watchdog.xcodeproj inside of the cloned repository directory and drag it into the Xcode' Project Navigator.
  • Configure your application target to be dependent on Watchdog.framework.
  • Link your application with the Watchdog.framework.
  • Add a "Copy Frameworks" build phase and add Watchdog.framework there.

Configuring Watchdog

ApplicationName-Info.plist

Watchdog requires you to define the following keys in your ApplicationName-Info.plist file:

<!-- The URL of the application purchasing page. -->
<key>WDGBuyOnlineURL</key>
<string>http://applicationapp.com/order</string>

<!-- The URL of the registration support page. -->
<key>WDGSupportURL</key>
<string>http://applicationapp.com/support/register</string>

<!-- The URL of the serial key validation script. -->
<key>WDGServerCheckURL</key>
<string>http://applicationapp/verify</string>

<!-- Custom URL scheme to inject customer name and a serial into the app. -->
<key>CFBundleURLTypes</key>
<array>
  <dict>
    <key>CFBundleTypeRole</key>
    <string>Viewer</string>
    <key>CFBundleURLIconFile</key>
    <string>SomeIcon.icns</string>
    <key>CFBundleURLName</key>
    <string>com.applicationapp.watchdog</string>
    <key>CFBundleURLSchemes</key>
    <array>
      <string>lowercasedappname-wd</string>
    </array>
  </dict>
</array>

WDGRegistrationController Singleton

At the launch time of your app (-applicationDidFinishLaunching:) request the WDGRegistrationController singleton instance and set its properies.

WDGRegistrationController* SRC = [WDGRegistrationController sharedRegistrationController];

Set the publicKeyPEM property to your application' DSA/ECDSA public key:

...
SRC.publicKeyPEM = @"-----BEGIN PUBLIC KEY-----\n ... -----END PUBLIC KEY-----";

Set the serialsStaticBlacklist property to the array of blacklisted serials (if you have some):

...
SRC.serialsStaticBlacklist = @(@"GAXAEFIAQCDINLKOVR4F6XFQUREC4RKX536WUFNFAIKQBCNWZF73M3YJCRWC76LRB3EUPD7D7SAWW", ...);

Using Watchdog

Observing states

Watchdog relies on a Key-Value Observing (KVO) mechanism to deliver information about application state changes. Add a relevant object as an observer of applicationState property to receive notifications when app transitions between Unknown|Unregistered|Registered states.

...
[SRC addObserver: self forKeyPath: @"applicationState" options: NSKeyValueObservingOptionInitial context: NULL];

Registering an app with concrete customer name & serial

Call -registerWithCustomerName:serial:handler: to asynchronously register application with concrete name and serial pair.

...
[SRC registerWithCustomerName: @"John" name serial: @"GAWRYTUILKJHVBNB..." handler: ^(WDGSerialVerdict verdict){ ... }];

Performing validation of a stored serial

Call -checkForStoredSerialAndValidateIt to asynchronously validate registration data, stored in User Defaults. This is most probably should be made only once during the application startup.

...
[SRC checkForStoredSerialAndValidateIt];

Wiping out stored registration data

Call -deauthorizeAccount to remove registration data from User Defaults and turn an app into the unregistered state.

...
[SRC deauthorizeAccount];

Watchdog Behavior

Application launches with no customer name and no serial stored in user defaults
→ Application silently goes to the unregistered state.

User clicks "Registration..." menu item at the top of the screen
→ Registration window is shown with the appropriate view (serial entry or registration status).

Application launches with stored customer name and serial and verification shows its incorrect
→ Error alert is displayed and application is set to the unregistered state.

Application is correctly registered but -deauthorizeAccount method is called
→ Application silently goes to the unregistered state.

User follows a Quick-Apply link
→ If registration data is incorrect error alert is displayed and app stays in unregistered state. If customer name conforms to the serial registration window is displayed with the status view.

Application is correctly registered but user follows a corrupted Quick-Apply Link
→ Application is deauthorized and error alert is displayed.

Quick-Apply Links

Instead of torturing customers with long serial keys consider using Quick-Apply Links to activate your apps.

Quick-Apply Link consists of the following parts:
applicationname-wd://CUSTOMERNAME:SERIAL

applicationname is a non-localized, lowercased name of your app, without any spaces. CUSTOMERNAME stands for Base32 encoded customer name and SERIAL is an actual serial (which is itself a Base32 encoded DSA/ECDSA signature of the customer' name).

HINT: Consider redirecting customers after successfull purchases to the corresponding Quick-Apply links to make seamless and trouble-free app-activation experiences.

Serials Blacklists

Static Blacklist

TODO:!

Dynamic Blacklist

TODO:!

Requirements

Watchdog utilizes Base Internationalization technology, thats why its minimum SDK is 10.8.

Localization

Watchdog' UI is currently localized to English and Russian.

Generating Keys

Choose an appropriate key length to keep a good ballance between security and length of a resulting serial.

Example Serials

Customer Name:
John Appleseed

1024 bit DSA serial:
GAWAEFA46ZQC6LB32U4S4OAPKMAY3DQP5FHSLEYCCQFTP4ZLD7EM5IJTQUX7NZVPLVXN7WYH3M

2048 bit DSA serial:
GAXAEFIAX2ZAZRGNXXBACEX4IIHEHSHSM66NUTVMAIKQB4UXRWTDMGV6L7RHCUYITVQYGKB5FS5S4

Compared to currently prevalent cryptosystems such as RSA and DSA, ECDSA offers equivalent security with smaller key sizes.

192 bit ECDSA serial (comparable to 1024 bit DSA):
GA2QEGAYX46LAYMZQSAFRCFWHC4FU73OLVH3HKKK3LM4GAQZADZNC3PVNFQIXA5EUZE5NJMTHDOIDH2YOTQGMSO2

384 bit ECDSA serial (comparable to 7680 bit DSA):
GBSQEMIA5K734JXT4ZEECT3MKTYD5MCYWZOXRZJ646R2AWYPN4ZXCFYZWNIHX4336BE5VFTY7VR4VVDQK2KNUARQMS3S3NAUNGPUIQ536RBVJOQUC2SQBIGLVC5LQKV3VCX7D6WTKNCKE3NMGMBCS4CC5DGMBOD6UMS4Q

TODO: citation needed.

DSA Keys

Generate a DSA private key:
$ openssl dsaparam -genkey 2048 -noout -out DSAPrivateKey.pem

Check components of the generated private key:
$ openssl dsa -in DSAPrivateKey.pem -text -noout

Extract public key from the private key:
$ openssl dsa -in DSAPrivateKey.pem -pubout -outform PEM -out DSAPublicKey.pem

ECDSA Keys

List all available curves:
$ openssl ecparam -list_curves

Generate an ECDSA private key:
$ openssl ecparam -genkey -name secp521r1 -noout -out ECDSAPrivateKey.pem

Check components of the generated private key:
$ openssl ec -in ECDSAPrivateKey.pem -text -noout

Extract public key from the private key:
$ openssl ec -in ECDSAPrivateKey.pem -pubout -outform PEM -out ECDSAPublicKey.pem

Important asymmetric cryptography notice

Keep your application' private key in a really safe place and make sure you have a reliable backup. If you lose your private key you no longer be able to generate new serials for your app. If your private key will be compromised, bad, really bad things will happen: anyone will be able to produce valid serials on their own so you most probably will have to change public key, embedded in your app. You have been warned!

Sandboxing

If you adding Watchdog to a sandboxed app you should put the following lines in your ApplicationName.entitlements:

<key>com.apple.security.network.client</key>
<true/>

FAQ

  • Q: How bulletproof Watchdog is?

    A: Objective-C by its nature is very dynamic and reflective. Rich metadata is preserved after compilation: class hierarchies, method signatures, strings, NIBs and so on... Tools like class-dump and Hopper allow to teardown your application to the atomic building blocks and even reconstruct it in pseudocode. There is no way to hide or protect your algorithms from an educated computer engineer.

  • Q: If Objective-C is so dynamic, why use it at all in a registration framework?

    A: Let's face the facts. Everybody loves simple high-level Cocoaesque-APIs that are no brainer. Even if you implement your registration handling code in a pure Assembler, smartasses torrenting you lovely app is just a matter of time (less) and demand (more). Every DRM system will be broken (think of iOS Jailbreak, numerous keygens, appname[k] torrents and so on...). We just have to keep honest people honest, without treating them like criminals and turning their app activation experience into hell.

License

Watchdog is released under the MIT license. See LICENSE.md.

watchdog's People

Contributors

konstantinpavlikhin avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

watchdog's Issues

Doesn't work with other curves other than secp384r1 and secp521r1...

Problem:

  • If the private key is generated using a curve different than secp384r1 and secp521r1, generated serials can't be validated.

Example:

$ openssl ecparam -genkey -name secp256k1 -noout -out private.pem

$ openssl ec -in private.pem -pubout -outform PEM -out public.pem

podspec file?

I see there was a podspec file, but it's removed for now. Is it possible to bring it back? Sparkle framework seems have solved the problem with static linking by building a framework and attaching to the release tag.

Couldn't build tests...

The problem:

  • can't install cocoapods required by the tests.
$ pod install

produces the following error:

Stack

   CocoaPods : 0.31.1
        Ruby : ruby 2.0.0p247 (2013-06-27 revision 41674) [universal.x86_64-darwin13]
    RubyGems : 2.0.3
        Host : Mac OS X 10.9.2 (13C64)
       Xcode : 5.1.1 (5B1008)
Ruby lib dir : /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib
Repositories : master - https://github.com/CocoaPods/Specs.git @ 717de2f3da4f6bb2f2b5f50976c6a08d776ad16e

Podfile

platform :osx, '10.8'

link_with 'WatchdogTests'

inhibit_all_warnings!

pod 'Specta', '~> 0.2'

pod 'Expecta', '~> 0.2'

xcodeproj 'Watchdog'

workspace 'Watchdog'

Error

Psych::SyntaxError - (/Users/tsenkov/.cocoapods/repos/master/CocoaPods-version.yml): mapping values are not allowed in this context at line 3 column 4
/System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/psych.rb:205:in `parse'
/System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/psych.rb:205:in `parse_stream'
/System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/psych.rb:153:in `parse'
/System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/psych.rb:129:in `load'
/System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/psych.rb:299:in `block in load_file'
/System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/psych.rb:299:in `open'
/System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/psych.rb:299:in `load_file'
/Library/Ruby/Gems/2.0.0/gems/cocoapods-0.31.1/lib/cocoapods/sources_manager.rb:262:in `version_information'
/Library/Ruby/Gems/2.0.0/gems/cocoapods-0.31.1/lib/cocoapods/sources_manager.rb:223:in `repo_compatible?'
/Library/Ruby/Gems/2.0.0/gems/cocoapods-0.31.1/lib/cocoapods/sources_manager.rb:282:in `master_repo_functional?'
/Library/Ruby/Gems/2.0.0/gems/cocoapods-0.31.1/lib/cocoapods/command.rb:39:in `parse'
/Library/Ruby/Gems/2.0.0/gems/claide-0.5.0/lib/claide/command.rb:243:in `parse'
/Library/Ruby/Gems/2.0.0/gems/cocoapods-0.31.1/lib/cocoapods/command.rb:38:in `parse'
/Library/Ruby/Gems/2.0.0/gems/claide-0.5.0/lib/claide/command.rb:275:in `run'
/Library/Ruby/Gems/2.0.0/gems/cocoapods-0.31.1/lib/cocoapods/command.rb:51:in `run'
/Library/Ruby/Gems/2.0.0/gems/cocoapods-0.31.1/bin/pod:33:in `<top (required)>'
/usr/bin/pod:23:in `load'
/usr/bin/pod:23:in `<main>'

WatchdogResources.bundle can't be found...

Spec:

  • OS X 10.9.2;
  • Xcode 5.1.1.

Problem:

  • When I try to display the registration window, Watchdog tries to find it's bundle with resources to get the path to window's xib, but is unable to find this bundle.

Code to reproduce it:

SRC = [WDRegistrationController sharedRegistrationController];

SRC.publicKeyPEM = @"-----BEGIN PUBLIC KEY-----\n....-----END PUBLIC KEY-----";
SRC.serialsStaticBlacklist = @[];
[SRC addObserver: self forKeyPath: ApplicationStateKeyPath options: NSKeyValueObservingOptionInitial context:nil];

[SRC checkForStoredSerialAndValidateIt];
if (SRC.applicationState < 2) {
    [SRC showRegistrationWindow:self];
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.