├── public ├── js │ ├── cryptojs │ │ ├── dumy │ │ ├── rollups │ │ │ ├── dummy │ │ │ └── aes.js │ │ └── components │ │ │ ├── dummy │ │ │ └── mode-ecb.js │ ├── des │ │ └── app.js │ ├── rabbit │ │ └── app.js │ ├── tripledes │ │ └── app.js │ ├── services.js │ ├── lib │ │ ├── plugins │ │ │ ├── CryptoJSCipher.js │ │ │ └── CryptoJSPassWordCipher.js │ │ └── angularjs-crypto.js │ ├── app.js │ └── controllers.js ├── partials │ ├── key.html │ ├── query.html │ ├── fullquery.html │ ├── empty.html │ ├── customjson.html │ ├── fulljson.html │ ├── fullbody.html │ ├── decryptbody.html │ ├── post.html │ └── get.html ├── test │ ├── e2e │ │ ├── protractor │ │ │ ├── fullquery.coffee │ │ │ ├── get.coffee │ │ │ ├── query.coffee │ │ │ ├── decodefullbody.coffee │ │ │ ├── fullbody.coffee │ │ │ └── post.coffee │ │ ├── karma │ │ │ ├── query.coffee │ │ │ ├── decodefullbody.coffee │ │ │ ├── fullquery.coffee │ │ │ ├── fullbody.coffee │ │ │ ├── get.coffee │ │ │ └── post.coffee │ │ └── plugins │ │ │ ├── mockAppRabbit.js │ │ │ ├── mockAppDes.js │ │ │ └── mockAppTripleDes.js │ └── unit │ │ └── controllersSpec.js ├── index-des.html ├── index-rabbit.html ├── index-tripledes.html ├── example │ └── index.html └── index.html ├── scripts ├── selenium.sh ├── karma.sh ├── karma-cont.sh ├── protractor.sh ├── e2etest.sh ├── e2etest-cont.sh └── e2etestprotractor.sh ├── .coveralls.yml ├── echoserver.js ├── .vagrant.yml ├── .bowerrc ├── .gitignore ├── karma ├── karma.conf-unit.js ├── karma.conf-e2esaucelabs.js ├── karma.conf-e2e.js ├── karma.conf-e2e-codio.js ├── protractor.conf.js ├── karma.conf-saucelabs.js └── karma-shared.conf.js ├── win_host_fix.sh ├── bower.json ├── upload_junitreport.sh ├── package.json ├── .travis.yml ├── server.js ├── wiredep_karma.js └── README.md /public/js/cryptojs/dumy: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /public/js/cryptojs/rollups/dummy: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /public/js/cryptojs/components/dummy: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /scripts/selenium.sh: -------------------------------------------------------------------------------- 1 | ./node_modules/protractor/bin/webdriver-manager start -------------------------------------------------------------------------------- /.coveralls.yml: -------------------------------------------------------------------------------- 1 | service_name: travis-ci 2 | repo_token: 5f0AQCQM1vrbCwhZgzaDJMFUQ4qNxsUha 3 | -------------------------------------------------------------------------------- /scripts/karma.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | ./node_modules/.bin/karma start karma/karma.conf-$1.js --single-run -------------------------------------------------------------------------------- /public/partials/key.html: -------------------------------------------------------------------------------- 1 |

set key local

2 | -------------------------------------------------------------------------------- /scripts/karma-cont.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | ./node_modules/.bin/karma start karma/karma.conf-$1.js --autoWatch -------------------------------------------------------------------------------- /scripts/protractor.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | node server.js&>application.log 3 | ./node_modules/protractor/bin/protractor karma/protractor.conf.js 4 | -------------------------------------------------------------------------------- /scripts/e2etest.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | node server.js&>application.log 3 | scripts/karma.sh $1 4 | #stop node server not nice but worked 5 | kill -9 $(ps aux | grep '\snode\s' | awk '{print $2}') -------------------------------------------------------------------------------- /echoserver.js: -------------------------------------------------------------------------------- 1 | var http = require('http'); 2 | 3 | http.createServer(function(request,response){ 4 | 5 | response.writeHead(200); 6 | request.pipe(response); 7 | 8 | }).listen(8080); 9 | -------------------------------------------------------------------------------- /scripts/e2etest-cont.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | node server.js&>application.log 3 | scripts/karma-cont.sh $1 4 | #stop node server not nice but worked 5 | kill -9 $(ps aux | grep '\snode\s' | awk '{print $2}') -------------------------------------------------------------------------------- /.vagrant.yml: -------------------------------------------------------------------------------- 1 | repo: 2 | - pussinboots/vagrant-devel 3 | folder: /vagrant/project/angularjs-crypto 4 | deps: 5 | - sublime3 6 | - firefox 7 | - nodejs 8 | - heroku 9 | - travis 10 | -------------------------------------------------------------------------------- /public/partials/query.html: -------------------------------------------------------------------------------- 1 |

Query parameter encoding

2 | 3 | plain query param {{plainQueryParam}} 4 | Send ajax request with query {{query}} 5 | 6 |

Json

7 |
8 | -------------------------------------------------------------------------------- /.bowerrc: -------------------------------------------------------------------------------- 1 | { 2 | "directory": "public/components", 3 | "json": "bower.json", 4 | "scripts": { 5 | "postinstall": "./wiredep_karma.js -s public/index.html -s karma/karma-shared.conf.js -i ../" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | .idea_modules 3 | coverage 4 | node_modules 5 | test-results.xml 6 | test-results-e2e.xml 7 | .dpl 8 | logs 9 | project/target 10 | project/project 11 | target 12 | public/components 13 | application.log 14 | -------------------------------------------------------------------------------- /public/partials/fullquery.html: -------------------------------------------------------------------------------- 1 |

Query parameter encoding

2 | 3 | plain query param {{plainQueryParam}} 4 |
5 |
6 | Send ajax request with query {{query}} 7 | 8 |

Client Data

9 | 10 | 11 |

Json Response

12 |
13 | -------------------------------------------------------------------------------- /public/partials/empty.html: -------------------------------------------------------------------------------- 1 |

Query parameter encoding

2 | 3 | plain query param {{queryParam}} 4 | Send ajax request with queryParameters {{queryParam}} 5 | 6 |
{{received}}
7 | 8 |

Client Data

9 | 10 | 11 |

Json

12 |
{{data}}
13 | -------------------------------------------------------------------------------- /scripts/e2etestprotractor.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | node server.js&>application.log 3 | ./node_modules/protractor/bin/webdriver-manager update 4 | sleep 10 5 | echo "start selenium" 6 | scripts/selenium.sh & 7 | sleep 5 8 | scripts/protractor.sh 9 | #stop node server not nice but worked 10 | kill -9 $(ps aux | grep '\snode\s' | awk '{print $2}') 11 | -------------------------------------------------------------------------------- /public/partials/customjson.html: -------------------------------------------------------------------------------- 1 |

Client Data

2 | 3 |
4 | 5 | 6 |

Json

7 |
8 | 9 |

Send to Server

10 | 11 |

Json

12 |
13 | -------------------------------------------------------------------------------- /public/partials/fulljson.html: -------------------------------------------------------------------------------- 1 |

Client Data

2 | 3 |
4 | 5 | 6 |

Json

7 |
8 | 9 |

Send to Server

10 | 11 |

Json

12 |
13 | -------------------------------------------------------------------------------- /public/partials/fullbody.html: -------------------------------------------------------------------------------- 1 |

Client Data

2 |
3 |
{{item.name_enc}}
4 |
{{item.value_enc}}
5 |
{{item.plain}}
6 | 7 |

Json

8 |
9 | 10 |

Request Body to Server

11 |
{{send.body}}
12 | -------------------------------------------------------------------------------- /public/partials/decryptbody.html: -------------------------------------------------------------------------------- 1 |

Client Data

2 |
3 |
{{item.name_enc}}
4 |
{{item.value_enc}}
5 |
{{item.plain}}
6 | 7 |

Json

8 |
9 | 10 |

Response Received From Server

11 | 12 |

Json

13 |
14 | 15 |
{{received}}
-------------------------------------------------------------------------------- /karma/karma.conf-unit.js: -------------------------------------------------------------------------------- 1 | // Karma configuration 2 | // Generated on Wed Aug 14 2013 22:33:43 GMT+0200 (CEST) 3 | var sharedConfig = require('./karma-shared.conf'); 4 | 5 | module.exports = function (config) { 6 | sharedConfig(config); 7 | config.set({ 8 | singleRun: false, 9 | proxies: { 10 | '/test/lib/angular/': 'http://localhost:8888/asset/test/lib/angular/' 11 | }, 12 | urlRoot: '/__karma/' 13 | }); 14 | 15 | config.files.push('public/test/**/*.js'); 16 | }; 17 | -------------------------------------------------------------------------------- /karma/karma.conf-e2esaucelabs.js: -------------------------------------------------------------------------------- 1 | var sharedConfig = require('./karma.conf-saucelabs.js'); 2 | 3 | module.exports = function (config) { 4 | sharedConfig(config); 5 | config.set({ 6 | files: [ 7 | 'node_modules/karma-ng-scenario/lib/angular-scenario.js', 8 | 'node_modules/karma-ng-scenario/lib/adapter.js', 9 | 'public/test/e2e/karma/*.coffee', 10 | ], 11 | reporters: ['progress', 'dots', 'junit'], 12 | junitReporter: { 13 | outputFile: 'test-results-e2e.xml', 14 | suite: 'End2End test' 15 | } 16 | }); 17 | } 18 | -------------------------------------------------------------------------------- /win_host_fix.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | base_folder="~" 4 | 5 | install() 6 | { 7 | #Check if win_host_fixes folder already exists 8 | if [ ! -d ~/win_host_fixes ]; then 9 | mkdir ~/win_host_fixes 10 | fi 11 | } 12 | 13 | create() 14 | { 15 | name="$base_folder/win_host_fixes/$$" 16 | 17 | while [ -d "$name" ] 18 | do 19 | name="$base_folder/win_host_fixes/$$" 20 | done 21 | 22 | eval "mkdir $name" 23 | 24 | eval "ln -s $name $1" 25 | } 26 | 27 | if [ -d $1 ]; then 28 | echo "Folder already exists, or no folder informed at all..." 29 | else 30 | install 31 | create $1 32 | fi -------------------------------------------------------------------------------- /public/partials/post.html: -------------------------------------------------------------------------------- 1 |

Client Data

2 |
3 |
{{item.name_enc}}
4 |
{{item.value_enc}}
5 |
{{item.plain}}
6 | 7 |

Json

8 |
9 | 10 |

Send to Server

11 |
12 |
{{item.name_enc}}
13 |
{{item.value_enc}}
14 |
{{item.plain}}
15 | 16 |

Json

17 |
18 | -------------------------------------------------------------------------------- /public/test/e2e/protractor/fullquery.coffee: -------------------------------------------------------------------------------- 1 | "use strict" 2 | 3 | describe "fullquery example", -> 4 | beforeEach -> 5 | browser.get "#/fullquery" 6 | expect(browser.getCurrentUrl()).toBe "http://localhost:9000/#/fullquery" 7 | 8 | it "check plain fullquery", -> 9 | expect(element(By.binding("plainQueryParam")).evaluate("plainQueryParam")).toEqual {name:"COMMERZBANK AG", value:12345, id:12345 } 10 | 11 | it "check encrypted query", -> 12 | expect(element(By.binding("query")).evaluate("query")).toEqual {query:"WZM2hwPXWx4+7SbaJpUPrh6KZl7c4lqZ/67En5tJy8DGTjW+mxDV0g8t2UtDklW4f1Ec/mr6hPf2K6V+oE/21A=="} -------------------------------------------------------------------------------- /karma/karma.conf-e2e.js: -------------------------------------------------------------------------------- 1 | var sharedConfig = require('./karma-shared.conf'); 2 | 3 | module.exports = function (config) { 4 | sharedConfig(config); 5 | config.files.push('node_modules/karma-ng-scenario/lib/angular-scenario.js'); 6 | config.files.push('node_modules/karma-ng-scenario/lib/adapter.js'); 7 | config.files.push('public/test/e2e/karma/*.coffee'); 8 | config.set({ 9 | reporters: ['progress', 'dots', 'junit'], 10 | junitReporter: { 11 | outputFile: 'test-results-e2e.xml', 12 | suite: 'End2End test' 13 | }, 14 | proxies: { 15 | '/': 'http://localhost:9000/' 16 | } 17 | }); 18 | } 19 | -------------------------------------------------------------------------------- /public/test/e2e/karma/query.coffee: -------------------------------------------------------------------------------- 1 | "use strict" 2 | describe "query example", -> 3 | it "should redirect /index.html to /index.html/#/query", -> 4 | browser().navigateTo "/index.html#/query" 5 | expect(browser().location().url()).toBe "/query" 6 | 7 | describe "query example", -> 8 | beforeEach -> 9 | browser().navigateTo "/index.html#/query" 10 | expect(browser().location().url()).toBe "/query" 11 | 12 | it "check plain query", -> 13 | expect(binding("query")).toEqual "{\"name_enc\":\"XJWoMnnOlSF3tFoU4jn4gg==\"}" 14 | 15 | it "check encrypted query", -> 16 | expect(binding("plainQueryParam")).toEqual "{\"name_enc\":\"COMMERZBANK AG\"}" 17 | -------------------------------------------------------------------------------- /public/test/e2e/protractor/get.coffee: -------------------------------------------------------------------------------- 1 | "use strict" 2 | describe "get example", -> 3 | beforeEach -> 4 | browser.get "/" 5 | expect(browser.getCurrentUrl()).toBe "http://localhost:9000/#/get" 6 | 7 | it "check count of encrypted items to be three", -> 8 | expect(element.all(By.repeater('item in received.items')).count()).toBe 3 9 | 10 | it "check encrypted name", -> 11 | expect(element.all(By.repeater('item in received.items').column('item.name_enc')).get(0).getText()).toEqual "XJWoMnnOlSF3tFoU4jn4gg==" 12 | 13 | it "check encrypted value", -> 14 | expect(element.all(By.repeater('item in received.items').column('item.value_enc')).get(0).getText()).toEqual "l0gZvr5oiHds8nQpqe0Kqg==" -------------------------------------------------------------------------------- /public/js/cryptojs/components/mode-ecb.js: -------------------------------------------------------------------------------- 1 | /* 2 | CryptoJS v3.1.2 3 | code.google.com/p/crypto-js 4 | (c) 2009-2013 by Jeff Mott. All rights reserved. 5 | code.google.com/p/crypto-js/wiki/License 6 | */ 7 | /** 8 | * Electronic Codebook block mode. 9 | */ 10 | CryptoJS.mode.ECB = (function () { 11 | var ECB = CryptoJS.lib.BlockCipherMode.extend(); 12 | 13 | ECB.Encryptor = ECB.extend({ 14 | processBlock: function (words, offset) { 15 | this._cipher.encryptBlock(words, offset); 16 | } 17 | }); 18 | 19 | ECB.Decryptor = ECB.extend({ 20 | processBlock: function (words, offset) { 21 | this._cipher.decryptBlock(words, offset); 22 | } 23 | }); 24 | 25 | return ECB; 26 | }()); 27 | -------------------------------------------------------------------------------- /public/test/e2e/protractor/query.coffee: -------------------------------------------------------------------------------- 1 | "use strict" 2 | describe "query example", -> 3 | it "should redirect /index.html to /index.html/#/query", -> 4 | browser.get "#/query" 5 | expect(browser.getCurrentUrl()).toBe "http://localhost:9000/#/query" 6 | 7 | describe "query example", -> 8 | beforeEach -> 9 | browser.get "#/query" 10 | expect(browser.getCurrentUrl()).toBe "http://localhost:9000/#/query" 11 | 12 | it "check plain query", -> 13 | browser.waitForAngular(); 14 | expect(element(By.binding("query")).evaluate("query")).toEqual {name_enc:"XJWoMnnOlSF3tFoU4jn4gg=="} 15 | 16 | it "check encrypted query", -> 17 | browser.waitForAngular(); 18 | expect(element(By.binding("plainQueryParam")).evaluate("plainQueryParam")).toEqual {name_enc:"COMMERZBANK AG"} -------------------------------------------------------------------------------- /public/test/e2e/karma/decodefullbody.coffee: -------------------------------------------------------------------------------- 1 | "use strict" 2 | 3 | describe "decode fullbody example", -> 4 | beforeEach -> 5 | browser().navigateTo "/index.html#/decryptbody" 6 | expect(browser().location().url()).toBe "/decryptbody" 7 | 8 | it "check count of encrypted items to be three", -> 9 | expect(repeater("div.plain").count()).toBe 1 10 | 11 | it "check plain name", -> 12 | expect(repeater("div.plain:eq(0)").column("item.name_enc")).toEqual ["COMMERZBANK AG"] 13 | 14 | it "check plain value", -> 15 | expect(repeater("div.plain:eq(0)").column("item.value_enc")).toEqual ["1504.75"] 16 | 17 | it "check encrypted body", -> 18 | expect(binding("received")).toEqual "{\"items\":[{\"name_enc\":\"COMMERZBANK AG\",\"value_enc\":\"1504.75\",\"plain\":\"Hallo\"}],\"count\":1}" -------------------------------------------------------------------------------- /public/test/e2e/karma/fullquery.coffee: -------------------------------------------------------------------------------- 1 | "use strict" 2 | describe "fullquery example", -> 3 | it "should redirect /index.html to /index.html/#/fullquery", -> 4 | browser().navigateTo "/index.html#/fullquery" 5 | expect(browser().location().url()).toBe "/fullquery" 6 | 7 | describe "fullquery example", -> 8 | beforeEach -> 9 | browser().navigateTo "/index.html#/fullquery" 10 | expect(browser().location().url()).toBe "/fullquery" 11 | 12 | it "check plain fullquery", -> 13 | expect(binding("plainQueryParam")).toEqual "{\"name\":\"COMMERZBANK AG\",\"value\":12345,\"id\":12345}" 14 | 15 | it "check encrypted query", -> 16 | expect(binding("query")).toEqual "{\"query\":\"WZM2hwPXWx4+7SbaJpUPrh6KZl7c4lqZ/67En5tJy8DGTjW+mxDV0g8t2UtDklW4f1Ec/mr6hPf2K6V+oE/21A==\"}" 17 | -------------------------------------------------------------------------------- /public/test/e2e/karma/fullbody.coffee: -------------------------------------------------------------------------------- 1 | "use strict" 2 | 3 | describe "fullbody example", -> 4 | beforeEach -> 5 | browser().navigateTo "/index.html#/fullbody" 6 | expect(browser().location().url()).toBe "/fullbody" 7 | 8 | it "check count of encrypted items to be three", -> 9 | expect(repeater("div.plain").count()).toBe 1 10 | 11 | it "check plain name", -> 12 | expect(repeater("div.plain:eq(0)").column("item.name_enc")).toEqual ["COMMERZBANK AG"] 13 | 14 | it "check plain value", -> 15 | expect(repeater("div.plain:eq(0)").column("item.value_enc")).toEqual ["1504.75"] 16 | 17 | it "check encrypted body", -> 18 | expect(binding("send.body")).toEqual "7fF8WOaj2HNvqhnOgvCNWFlxbNFX3N2Fi13ueR/Fe5kT5/pZGp1oVUw+ZYIgv7ST/Ke4+F5/8JXQI87/mpHVlNF6UrYEHrqAnj0gewtcwQ20lf+Kc4aSaXwJN8XJuNYy" -------------------------------------------------------------------------------- /public/test/e2e/karma/get.coffee: -------------------------------------------------------------------------------- 1 | "use strict" 2 | describe "get example", -> 3 | it "should redirect /index.html to /index.html/#/get", -> 4 | browser().navigateTo "/index.html" 5 | expect(browser().location().url()).toBe "/get" 6 | 7 | describe "get example", -> 8 | beforeEach -> 9 | browser().navigateTo "/index.html#/get" 10 | expect(browser().location().url()).toBe "/get" 11 | 12 | it "check count of encrypted items to be three", -> 13 | expect(repeater("div.encrypted").count()).toBe 3 14 | 15 | it "check encrypted name", -> 16 | expect(repeater("div.encrypted:eq(0)").column("item.name_enc")).toEqual ["XJWoMnnOlSF3tFoU4jn4gg=="] 17 | 18 | it "check encrypted value", -> 19 | expect(repeater("div.encrypted:eq(0)").column("item.value_enc")).toEqual ["l0gZvr5oiHds8nQpqe0Kqg=="] -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angularjs-crypto", 3 | "version": "1.4.0", 4 | "homepage": "https://github.com/pussinboots/angularjs-crypto", 5 | "authors": [ 6 | "pussinboots " 7 | ], 8 | "license": "MIT", 9 | "ignore": [ 10 | "**/.*", 11 | "node_modules", 12 | "bower_components", 13 | "public/components", 14 | "test", 15 | "tests" 16 | ], 17 | "main": [ 18 | "public/js/lib/angularjs-crypto.js", 19 | "public/js/lib/plugins/CryptoJSCipher.js", 20 | "public/js/lib/ContentHeaderCheck.js" 21 | ], 22 | "dependencies": { 23 | "angular": "1.3.13", 24 | "angular-cookies": "1.3.13", 25 | "angular-resource": "1.3.13", 26 | "angular-route": "1.3.13", 27 | "bootstrap": "~3.3.1", 28 | "angular-highlightjs": "~0.3.2" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /upload_junitreport.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | owner=pussinboots 3 | project=angularjs-crypto 4 | endpoint=unitcover.herokuapp.com 5 | trigger="trigger=Travis" 6 | travisBuildId="" 7 | if [[ -n ${TRAVIS} ]] 8 | then 9 | echo "travis build detected" 10 | travisBuildId="&travisBuildId=$TRAVIS_BUILD_ID" 11 | else 12 | trigger="trigger=Local" 13 | fi 14 | #upload play junit reports 15 | buildnumber=$(curl -s -X POST http://$endpoint/api/$owner/$project/builds?$trigger$travisBuildId | sed -E 's/.*"buildNumber":([0-9]*).*/\1/') 16 | echo $buildnumber 17 | echo "http://$endpoint/api/$owner/$project/$buildnumber" 18 | 19 | curl -H "Content-Type:application/xml" -X POST -d @test-results.xml http://$endpoint/api/$owner/$project/$buildnumber 20 | 21 | curl -X POST http://$endpoint/api/$owner/$project/builds/$buildnumber/end 22 | -------------------------------------------------------------------------------- /public/test/e2e/protractor/decodefullbody.coffee: -------------------------------------------------------------------------------- 1 | "use strict" 2 | 3 | describe "decode fullbody example", -> 4 | beforeEach -> 5 | browser.get "#/decryptbody" 6 | expect(browser.getCurrentUrl()).toBe "http://localhost:9000/#/decryptbody" 7 | 8 | it "check count of encrypted items to be three", -> 9 | expect(element.all(By.repeater('item in data.items')).count()).toBe 1 10 | 11 | it "check plain name", -> 12 | expect(element.all(By.repeater('item in data.items').column('item.name_enc')).get(0).getText()).toEqual "COMMERZBANK AG" 13 | 14 | it "check plain value", -> 15 | expect(element.all(By.repeater('item in data.items').column('item.value_enc')).get(0).getText()).toEqual "1504.75" 16 | 17 | it "check encrypted body", -> 18 | expect(element(By.binding("received")).evaluate("received.items")).toEqual [{name_enc:"COMMERZBANK AG" ,value_enc:"1504.75",plain:"Hallo"}] -------------------------------------------------------------------------------- /karma/karma.conf-e2e-codio.js: -------------------------------------------------------------------------------- 1 | var sharedConfig = require('./karma.conf-unit.js'); 2 | var hostname = require('os').hostname() + '.codio.io'; 3 | var proxyHost = 'http://' + hostname + ':9000/'; 4 | 5 | module.exports = function (config) { 6 | sharedConfig(config); 7 | config.files.push('public/test/e2e/karma/*.coffee'); 8 | 9 | config.set({ 10 | files: [ 11 | 'node_modules/karma-ng-scenario/lib/angular-scenario.js', 12 | 'node_modules/karma-ng-scenario/lib/adapter.js', 13 | 'public/test/e2e/karma/*.coffee', 14 | ], 15 | reporters: ['progress', 'dots', 'junit'], 16 | junitReporter: { 17 | outputFile: 'test-results-e2e.xml', 18 | suite: 'End2End test' 19 | }, 20 | port: 9002, 21 | browsers: ['PhantomJS'], 22 | hostname: hostname, 23 | proxies: { 24 | '/': proxyHost 25 | } 26 | }); 27 | } -------------------------------------------------------------------------------- /public/test/e2e/karma/post.coffee: -------------------------------------------------------------------------------- 1 | "use strict" 2 | 3 | describe "post example", -> 4 | beforeEach -> 5 | browser().navigateTo "/index.html#/post" 6 | expect(browser().location().url()).toBe "/post" 7 | 8 | it "check count of encrypted items to be three", -> 9 | expect(repeater("div.plain").count()).toBe 1 10 | 11 | it "check plain name", -> 12 | expect(repeater("div.plain:eq(0)").column("item.name_enc")).toEqual ["COMMERZBANK AG", "XJWoMnnOlSF3tFoU4jn4gg=="] 13 | 14 | it "check plain value", -> 15 | expect(repeater("div.plain:eq(0)").column("item.value_enc")).toEqual ["1504.75", "l0gZvr5oiHds8nQpqe0Kqg=="] 16 | 17 | it "check encrypted name", -> 18 | expect(repeater("div.encrypted:eq(0)").column("item.name_enc")).toEqual [ "XJWoMnnOlSF3tFoU4jn4gg=="] 19 | 20 | it "check encrypted value", -> 21 | expect(repeater("div.encrypted:eq(0)").column("item.value_enc")).toEqual ["l0gZvr5oiHds8nQpqe0Kqg=="] -------------------------------------------------------------------------------- /public/test/e2e/protractor/fullbody.coffee: -------------------------------------------------------------------------------- 1 | "use strict" 2 | 3 | describe "fullbody example", -> 4 | beforeEach -> 5 | browser.get "#/fullbody" 6 | expect(browser.getCurrentUrl()).toBe "http://localhost:9000/#/fullbody" 7 | 8 | it "check count of encrypted items to be three", -> 9 | expect(element.all(By.repeater('item in data.items')).count()).toBe 1 10 | 11 | it "check plain name", -> 12 | expect(element.all(By.repeater('item in data.items').column('item.name_enc')).get(0).getText()).toEqual "COMMERZBANK AG" 13 | 14 | it "check plain value", -> 15 | expect(element.all(By.repeater('item in data.items').column('item.value_enc')).get(0).getText()).toEqual "1504.75" 16 | 17 | it "check encrypted body", -> 18 | expect(element(By.binding("send.body")).evaluate("send.body")).toEqual "7fF8WOaj2HNvqhnOgvCNWFlxbNFX3N2Fi13ueR/Fe5kT5/pZGp1oVUw+ZYIgv7ST/Ke4+F5/8JXQI87/mpHVlNF6UrYEHrqAnj0gewtcwQ20lf+Kc4aSaXwJN8XJuNYy" -------------------------------------------------------------------------------- /public/test/e2e/protractor/post.coffee: -------------------------------------------------------------------------------- 1 | "use strict" 2 | 3 | describe "post example", -> 4 | beforeEach -> 5 | browser.get "#/post" 6 | expect(browser.getCurrentUrl()).toBe "http://localhost:9000/#/post" 7 | 8 | it "check count of encrypted items to be three", -> 9 | expect(element.all(By.repeater('item in data.items')).count()).toBe 1 10 | 11 | it "check plain name", -> 12 | expect(element.all(By.repeater('item in data.items').column('item.name_enc')).get(0).getText()).toEqual "COMMERZBANK AG" 13 | 14 | it "check plain value", -> 15 | expect(element.all(By.repeater('item in data.items').column('item.value_enc')).get(0).getText()).toEqual "1504.75" 16 | 17 | it "check encrypted name", -> 18 | expect(element.all(By.repeater('item in send.items').column('item.name_enc')).get(0).getText()).toEqual "XJWoMnnOlSF3tFoU4jn4gg==" 19 | 20 | it "check encrypted value", -> 21 | expect(element.all(By.repeater('item in send.items').column('item.value_enc')).get(0).getText()).toEqual "l0gZvr5oiHds8nQpqe0Kqg==" -------------------------------------------------------------------------------- /public/partials/get.html: -------------------------------------------------------------------------------- 1 | Demonstrate a simple http get scenario of partial encrypted json data. The server send a json object that contains 2 | some encrypted field data. The encrypted field names ends with _enc that tells the angularjs-crypto library to decode it automaticly. 3 | 4 |

Received from Server

5 |
6 |
{{item.name_enc}}
7 |
{{item.value_enc}}
8 |
{{item.plain}}
9 |
10 | 11 |

Json received from Server

12 |
13 | 14 | The json data will be decrypted on the client side by the angularjs-crypto library. 15 | 16 |

Client Side decrypted Data

17 | 18 |
19 |
{{item.name_enc}}
20 |
{{item.value_enc}}
21 |
{{item.plain}}
22 |
23 | 24 |

Json decrypted

25 |
26 |
27 |
28 | -------------------------------------------------------------------------------- /karma/protractor.conf.js: -------------------------------------------------------------------------------- 1 | require('coffee-script').register(); 2 | 3 | exports.config = { 4 | seleniumAddress: 'http://localhost:4444/wd/hub', 5 | capabilities: { 6 | 'browserName': 'chrome', 7 | 'chromeOptions': { 8 | 'args': ['no-sandbox'] 9 | } 10 | }, 11 | specs: [ 12 | '../public/test/e2e/protractor/*.coffee' 13 | ], 14 | framework: 'jasmine', 15 | allScriptsTimeout: 20000, 16 | baseUrl: 'http://localhost:9000/', 17 | onPrepare: function() { 18 | // The require statement must be down here, since jasmine-reporters 19 | // needs jasmine to be in the global and protractor does not guarantee 20 | // this until inside the onPrepare function. 21 | require('jasmine-reporters'); 22 | jasmine.getEnv().addReporter( 23 | new jasmine.JUnitXmlReporter('./', true, true, 'protractor.', true) 24 | ); 25 | var ScreenShotReporter = require('protractor-screenshot-reporter'); 26 | jasmine.getEnv().addReporter( 27 | new ScreenShotReporter({baseDirectory: '/tmp/screenshots'}) 28 | ); 29 | }, 30 | } 31 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angularjs-crypto", 3 | "version": "0.0.1", 4 | "dependencies": { 5 | "bower": "^1.3.12", 6 | "connect": "^3.3.4", 7 | "serve-static": "^1.8.1", 8 | "wiredep": "^1.7.2", 9 | "coffee-script": "~1.9.0" 10 | }, 11 | "engines": { 12 | "node": "0.10.x" 13 | }, 14 | "main": [ 15 | "public/js/lib/angularjs-crypto.js" 16 | ], 17 | "scripts": { 18 | "test": "./node_modules/.bin/karma start karma/karma.conf-$JOB.js --single-run", 19 | "postinstall": "./node_modules/bower/bin/bower install" 20 | }, 21 | "devDependencies": { 22 | "karma": "^0.12.31", 23 | "karma-chrome-launcher": "^0.1.7", 24 | "karma-cli": "0.0.4", 25 | "karma-coverage": "^0.2.7", 26 | "karma-coveralls": "^0.1.5", 27 | "karma-firefox-launcher": "~0.1.4", 28 | "karma-jasmine": "^0.1.5", 29 | "karma-junit-reporter": "^0.2.2", 30 | "karma-ng-scenario": "~0.1", 31 | "karma-opera-launcher": "~0.1", 32 | "karma-phantomjs-launcher": "~0.1.4", 33 | "karma-sauce-launcher": "^0.2.10", 34 | "karma-script-launcher": "~0.1", 35 | "karma-threshold-reporter": "~0.1.6", 36 | "karma-coffee-preprocessor": "~0.2.1", 37 | "jasmine-reporters": "^1.0.0", 38 | "protractor": "~1.6.1", 39 | "protractor-screenshot-reporter": "~0.0.5" 40 | } 41 | } -------------------------------------------------------------------------------- /public/js/des/app.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /* App Module */ 4 | var demoApp = angular.module('demoApp', ['services', 'angularjs-crypto', 'ngRoute']); 5 | 6 | demoApp.config(function ($routeProvider) { 7 | $routeProvider 8 | .when('/get', { templateUrl: 'partials/get.html', controller: DecodeGetController}) 9 | .when('/query', { templateUrl: 'partials/query.html', controller: EncodeQueryGetController}) 10 | .when('/fullquery', { templateUrl: 'partials/fullquery.html', controller: EncodeFullQueryGetController}) 11 | .when('/fullbody', { templateUrl: 'partials/fullbody.html', controller: EncodeBodyPostController}) 12 | .when('/empty', { templateUrl: 'partials/empty.html', controller: EmptyController}) 13 | .when('/post', { templateUrl: 'partials/post.html', controller: EncodePostController}) 14 | .when('/key', { templateUrl: 'partials/key.html'}) 15 | .otherwise({ redirectTo: '/get' }); 16 | }); 17 | 18 | demoApp.run(function(cfCryptoHttpInterceptor, $rootScope) { 19 | $rootScope.base64Key = "16rdKQfqN3L4TY7YktgxBw=="; 20 | cfCryptoHttpInterceptor.base64Key = $rootScope.base64Key; 21 | cfCryptoHttpInterceptor.pattern = "_enc"; //default value but for a better understanding it is also defined here 22 | cfCryptoHttpInterceptor.plugin = new CryptoJSCipher(CryptoJS.mode.ECB, CryptoJS.pad.Pkcs7, CryptoJS.DES) 23 | }) 24 | -------------------------------------------------------------------------------- /public/js/rabbit/app.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /* App Module */ 4 | var demoApp = angular.module('demoApp', ['services', 'angularjs-crypto', 'ngRoute']); 5 | 6 | demoApp.config(function ($routeProvider) { 7 | $routeProvider 8 | .when('/get', { templateUrl: 'partials/get.html', controller: DecodeGetController}) 9 | .when('/query', { templateUrl: 'partials/query.html', controller: EncodeQueryGetController}) 10 | .when('/fullquery', { templateUrl: 'partials/fullquery.html', controller: EncodeFullQueryGetController}) 11 | .when('/fullbody', { templateUrl: 'partials/fullbody.html', controller: EncodeBodyPostController}) 12 | .when('/empty', { templateUrl: 'partials/empty.html', controller: EmptyController}) 13 | .when('/post', { templateUrl: 'partials/post.html', controller: EncodePostController}) 14 | .when('/key', { templateUrl: 'partials/key.html'}) 15 | .otherwise({ redirectTo: '/get' }); 16 | }); 17 | 18 | demoApp.run(function(cfCryptoHttpInterceptor, $rootScope) { 19 | $rootScope.base64Key = "16rdKQfqN3L4TY7YktgxBw=="; 20 | cfCryptoHttpInterceptor.base64Key = $rootScope.base64Key; 21 | cfCryptoHttpInterceptor.pattern = "_enc"; //default value but for a better understanding it is also defined here 22 | cfCryptoHttpInterceptor.plugin = new CryptoJSCipher(CryptoJS.mode.ECB, CryptoJS.pad.Pkcs7, CryptoJS.Rabbit) 23 | }) 24 | -------------------------------------------------------------------------------- /public/js/tripledes/app.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /* App Module */ 4 | var demoApp = angular.module('demoApp', ['services', 'angularjs-crypto', 'ngRoute']); 5 | 6 | demoApp.config(function ($routeProvider) { 7 | $routeProvider 8 | .when('/get', { templateUrl: 'partials/get.html', controller: DecodeGetController}) 9 | .when('/query', { templateUrl: 'partials/query.html', controller: EncodeQueryGetController}) 10 | .when('/fullquery', { templateUrl: 'partials/fullquery.html', controller: EncodeFullQueryGetController}) 11 | .when('/fullbody', { templateUrl: 'partials/fullbody.html', controller: EncodeBodyPostController}) 12 | .when('/empty', { templateUrl: 'partials/empty.html', controller: EmptyController}) 13 | .when('/post', { templateUrl: 'partials/post.html', controller: EncodePostController}) 14 | .when('/key', { templateUrl: 'partials/key.html'}) 15 | .otherwise({ redirectTo: '/get' }); 16 | }); 17 | 18 | demoApp.run(function(cfCryptoHttpInterceptor, $rootScope) { 19 | $rootScope.base64Key = "16rdKQfqN3L4TY7YktgxBw=="; 20 | cfCryptoHttpInterceptor.base64Key = $rootScope.base64Key; 21 | cfCryptoHttpInterceptor.pattern = "_enc"; //default value but for a better understanding it is also defined here 22 | cfCryptoHttpInterceptor.plugin = new CryptoJSCipher(CryptoJS.mode.ECB, CryptoJS.pad.Pkcs7, CryptoJS.TripleDES) 23 | }) 24 | -------------------------------------------------------------------------------- /public/js/services.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /* Services */ 4 | 5 | angular.module('services', ['ngResource'], function ($provide) { 6 | 7 | $provide.factory('Data', function ($resource) { 8 | return $resource('/assets/config', {}, { 9 | get: {url:'/data/get/aes', method: 'GET', isArray: false, crypt: true}, 10 | query: {url:'/data/query', method: 'GET', isArray: false, crypt: true}, 11 | queryNoDecrypt: {url:'/data/query', method: 'GET', isArray: false, crypt: true, decrypt: false}, 12 | queryFullCrypt: {url:'/data/query', method: 'GET', isArray: false, fullcryptquery:true}, 13 | queryNoCrypt: {url:'/data/get/aes', method: 'GET'}, 14 | save: {url:'/data', method: 'POST', crypt: true}, 15 | saveFullJson: {url:'/data', method: 'POST', crypt: true, pattern: '*'}, 16 | saveNoCrypt: {url:'/data', method: 'POST'}, 17 | saveEnCrypt: {url:'/data', method: 'POST', isArray: true, fullcryptbody:true, 18 | transformResponse: function (data, headers) { 19 | return [{ body: data }]; 20 | //return data; 21 | } 22 | }, 23 | saveDeCrypt: {url:'/data/decrypt', method: 'POST', isArray: false, fullcryptbody:true, decryptbody:true, 24 | transformResponse: function (data, headers) { 25 | return data; 26 | } 27 | } 28 | }); 29 | }); 30 | }); 31 | -------------------------------------------------------------------------------- /public/js/lib/plugins/CryptoJSCipher.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | function CryptoJSCipher(mode, padding, Cipher) { 3 | var mode = mode; 4 | var padding = padding; 5 | var Cipher = Cipher; 6 | return { 7 | encode: function(plainValue, base64Key) { 8 | if (!plainValue) { return plainValue; } 9 | if (base64Key.length<=0) return plainValue; 10 | 11 | var key = CryptoJS.enc.Base64.parse(base64Key); 12 | // this is the decrypted data as a sequence of bytes 13 | var encryprtedData = Cipher.encrypt(plainValue, key, { 14 | mode: mode, 15 | padding: padding 16 | }); 17 | //var encryprtedValue = encryprtedData.toString( CryptoJS.enc.Base64); 18 | return encryprtedData.toString(); 19 | }, 20 | decode : function(encryptedValue, base64Key) { 21 | if (base64Key.length<=0) return encryptedValue; 22 | var key = CryptoJS.enc.Base64.parse(base64Key); 23 | // this is the decrypted data as a sequence of bytes 24 | var decryptedData = Cipher.decrypt(encryptedValue, key, { 25 | mode: mode, 26 | padding: padding 27 | }); 28 | return decryptedData.toString(CryptoJS.enc.Utf8); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /public/js/lib/plugins/CryptoJSPassWordCipher.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | function CryptoJSPassWordCipher(mode, padding, Cipher) { 3 | var mode = mode; 4 | var padding = padding; 5 | var Cipher = Cipher; 6 | return { 7 | encode: function(plainValue, password) { 8 | if (!plainValue) { return plainValue; } 9 | if (password.length<=0) return plainValue; 10 | var key = CryptoJS.SHA3(password, { outputLength: 256 }); 11 | // this is the decrypted data as a sequence of bytes 12 | var encryprtedData = Cipher.encrypt(plainValue, key, { 13 | mode: mode, 14 | padding: padding 15 | }); 16 | //var encryprtedValue = encryprtedData.toString( CryptoJS.enc.Base64); 17 | return encryprtedData.toString(); 18 | }, 19 | decode : function(encryptedValue, password) { 20 | if (password.length<=0) return encryptedValue; 21 | var key = CryptoJS.SHA3(password, { outputLength: 256 }); 22 | // this is the decrypted data as a sequence of bytes 23 | var decryptedData = Cipher.decrypt(encryptedValue, key, { 24 | mode: mode, 25 | padding: padding 26 | }); 27 | return decryptedData.toString(CryptoJS.enc.Utf8); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /karma/karma.conf-saucelabs.js: -------------------------------------------------------------------------------- 1 | // Karma configuration 2 | var sharedConfig = require('./karma.conf-unit'); 3 | 4 | module.exports = function (config) { 5 | var customLaunchers= { 6 | 'SL_Chrome': { 7 | base: 'SauceLabs', 8 | browserName: 'chrome', 9 | version: '43' 10 | }, 11 | 'SL_Firefox': { 12 | base: 'SauceLabs', 13 | browserName: 'firefox', 14 | version: '26' 15 | }, 16 | 'SL_Safari': { 17 | base: 'SauceLabs', 18 | browserName: 'safari', 19 | platform: 'OS X 10.9', 20 | version: '7' 21 | }, 22 | 'SL_IE_11': { 23 | base: 'SauceLabs', 24 | browserName: 'internet explorer', 25 | platform: 'Windows 8.1', 26 | version: '11' 27 | } 28 | }; 29 | 30 | sharedConfig(config); 31 | 32 | config.set({ 33 | sauceLabs: { 34 | testName: 'Karma and Sauce Labs demo', 35 | recordScreenshots: false 36 | }, 37 | 38 | customLaunchers: customLaunchers, 39 | browsers: Object.keys(customLaunchers), 40 | 41 | // If browser does not capture in given timeout [ms], kill it 42 | captureTimeout: 120000, 43 | browserDisconnectTimeout: 10000, 44 | browserDisconnectTolerance: 2, 45 | browserNoActivityTimeout: 20000, 46 | 47 | // Continuous Integration mode 48 | // if true, it capture browsers, run tests and exit 49 | singleRun: true, 50 | 51 | proxies: { 52 | '/test/lib/angular/': 'http://localhost:8888/asset/test/lib/angular/' 53 | }, 54 | 55 | urlRoot: '/__karma/' 56 | }); 57 | }; 58 | -------------------------------------------------------------------------------- /public/js/app.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /* App Module */ 4 | var demoApp = angular.module('demoApp', ['services', 'angularjs-crypto', 'ngRoute', 'hljs']); 5 | 6 | demoApp.config(function ($routeProvider) { 7 | $routeProvider 8 | .when('/get', { templateUrl: 'partials/get.html', controller: DecodeGetController}) 9 | .when('/query', { templateUrl: 'partials/query.html', controller: EncodeQueryGetController}) 10 | .when('/fullquery', { templateUrl: 'partials/fullquery.html', controller: EncodeFullQueryGetController}) 11 | .when('/fullbody', { templateUrl: 'partials/fullbody.html', controller: EncodeBodyPostController}) 12 | .when('/decryptbody', { templateUrl: 'partials/decryptbody.html', controller: DecodeBodyPostController}) 13 | .when('/customjson', { templateUrl: 'partials/customjson.html', controller: CustomJsonEncodeController}) 14 | .when('/fulljson', { templateUrl: 'partials/fulljson.html', controller: FullJsonEncodeController}) 15 | .when('/empty', { templateUrl: 'partials/empty.html', controller: EmptyController}) 16 | .when('/post', { templateUrl: 'partials/post.html', controller: EncodePostController}) 17 | .when('/key', { templateUrl: 'partials/key.html'}) 18 | .otherwise({ redirectTo: '/get' }); 19 | }); 20 | /*demoApp.config(['$httpProvider', function ($httpProvider) { 21 | $httpProvider.interceptors.push('cryptoHttpInterceptor'); 22 | }]);*/ 23 | demoApp.run(function(cfCryptoHttpInterceptor, $rootScope) { 24 | $rootScope.base64Key = "16rdKQfqN3L4TY7YktgxBw=="; 25 | cfCryptoHttpInterceptor.base64Key = $rootScope.base64Key; 26 | cfCryptoHttpInterceptor.pattern = "_enc"; //default value but for a better understanding it is also defined here 27 | }) 28 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | before_script: 3 | #- wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | sudo apt-key add - 4 | #- sudo sh -c 'echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list' 5 | #- sudo apt-get update 6 | #- sudo apt-get install -y --force-yes google-chrome-stable 7 | - wget -q -O - https://dl.google.com/linux/linux_signing_key.pub | sudo apt-key add - 8 | - sudo apt-get update 9 | - sudo apt-get install chromium-browser 10 | - export DISPLAY=:99.0 11 | - sh -e /etc/init.d/xvfb start 12 | node_js: 13 | - 0.1 14 | deploy: 15 | provider: heroku 16 | app: angularjs-crypto 17 | strategy: git 18 | api_key: 19 | secure: nQ9G863kXSWi+AC/Xreiz1/bGTikFfU+0MNQY6NkvMh3A7vJjQP52cpOcVsSnJi8oekTYrbJDj/aswSSXSoJI5ftvxjBU5GwGyB6gjJQRtMGMn3IBgc9X19vW4NGqX5Y2aQRoJOfHy2A1sKrkycfEdy/x8Z3jhoPHG1+Pi0lLNQ= 20 | after_failure: 21 | - wget -O - https://unitcover.herokuapp.com/scripts/upload.sh | bash /dev/stdin pussinboots angularjs-crypto "." 22 | before_deploy: 23 | - scripts/e2etestprotractor.sh 24 | - wget -O - https://unitcover.herokuapp.com/scripts/upload.sh | bash /dev/stdin pussinboots angularjs-crypto "." 25 | - if [[ -a .git/shallow ]]; then git fetch --unshallow; fi 26 | notifications: 27 | webhooks: 28 | urls: 29 | - https://webhooks.gitter.im/e/69a4be3312f3f3a0a25b 30 | on_success: always 31 | on_failure: always 32 | on_start: false 33 | env: 34 | matrix: 35 | - JOB=saucelabs 36 | global: 37 | - secure: Ru3VCdqIFZgf9if2Ca/ChGFZq6Q44ZzNV0qMdP6w6aWLIWFv2I3RXm5BDsIdahqEVEP/8O6i8wChojVZn9QLc0OMwy/qyljYB0fb9HJ1rwpHiJ9/B8hxkZr+BtvdJ8jHU9c+x9mUf+j6WWnY1DX4OPEPp0zEcdyhP0nQ7cCzTA8= 38 | - secure: iN1FgOjfMKze9gDfrIMO1oCXL87/Tpkj9aZ1G9Dpz0ACQke3msdP13Lpy5ZWuFYA0inzA1DiQKpUK8lD2+SJd54PmrZdZMDVgxSSgq/5IwYrINb5hN+X7APYh0bCl4UwKhD278wiyy5HhfKX/fsj8e+tWieR4atk6jzMxBHikXE= 39 | -------------------------------------------------------------------------------- /public/index-des.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | angularjs-crypto DES Demo 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 |
38 | 39 | 40 | -------------------------------------------------------------------------------- /public/index-rabbit.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | angularjs-crypto DES Demo 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 |
38 | 39 | 40 | -------------------------------------------------------------------------------- /public/index-tripledes.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | angularjs-crypto DES Demo 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 |
38 | 39 | 40 | -------------------------------------------------------------------------------- /public/test/e2e/plugins/mockAppRabbit.js: -------------------------------------------------------------------------------- 1 | var myAppDev = angular.module('demoApp-e2e', ['demoApp', 'ngMockE2E']); 2 | 3 | myAppDev.run(["$httpBackend", function ($httpBackend) { 4 | $httpBackend.whenGET('/assets/config').respond(givenEncodedWithFieldNames(), {'content-type': 'application/json;charset=utf-8'}); 5 | $httpBackend.whenGET('/assets/config').respond(givenEncodedWithFieldNames(), {'content-type': 'application/json;charset=utf-8'}); 6 | $httpBackend.whenGET('/assets/config?name_enc=d%2Fjahqgd7BBM1MklteU%3D').respond(givenEncodedWithFieldNames(), {'content-type': 'application/json;charset=utf-8'}); 7 | $httpBackend.whenGET('/assets/config?query=T5X5qoAqlGgv2c1IuecTkg%2FqGqozL6mzBjvH1QenqXrJjjlDF%2FIGMwyyd0ltb%2FUbwCw%3D').respond(givenEncodedWithFieldNames(), {'Content-Type': 'application/json;charset=utf-8'}); 8 | $httpBackend.whenPOST('/assets/config', 'T5X+v4gixXA3wfknmsMsrRLOOoIxVMzSZVT88TmIjhm99CsxZOUGMxO3OQY5AqNBlnMy0+l8AYN0ejc860+tRUd5ft5Z2XPAE1aEYhaqceXUG+NMUAcB5YQ=').respond({body:'T5X+v4gixXA3wfknmsMsrRLOOoIxVMzSZVT88TmIjhm99CsxZOUGMxO3OQY5AqNBlnMy0+l8AYN0ejc860+tRUd5ft5Z2XPAE1aEYhaqceXUG+NMUAcB5YQ='}, {'content-type': 'application/json;charset=utf-8'}); 9 | $httpBackend.whenPOST('/assets/config', givenProfile()).respond(200); 10 | $httpBackend.whenPOST('/assets/empty').respond(null, {'content-type': 'application/json;charset=utf-8'}); 11 | $httpBackend.whenGET(/partials\/.*/).passThrough(); 12 | }]); 13 | 14 | //given 15 | function givenProfile() { 16 | return { items: [ 17 | {name_enc: "d/jahqgd7BBM1MklteU=", value_enc: "BYKn/8N4gw==", plain: "Hallo"} 18 | ], 19 | count: 1 20 | } 21 | } 22 | 23 | function givenEncodedWithFieldNames() { 24 | return { items: [ 25 | {name_enc: "d/jahqgd7BBM1MklteU=", value_enc: "BYKn/8N4gw==", plain: "Hallo"}, 26 | {name_enc: "d/jahqgd7BBM1MklteU=", value_enc: "BYKn/8N4gw==", plain: "Hallo"}, 27 | {name_enc: "d/jahqgd7BBM1MklteU=", value_enc: "BYKn/8N4gw=="} 28 | ], 29 | count: 3 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /server.js: -------------------------------------------------------------------------------- 1 | var connect = require('connect'); 2 | var serveStatic = require('serve-static'); 3 | var url = require('url'); 4 | var port = Number(process.env.PORT || 9000); 5 | connect(). 6 | use('/data/get/aes', function getaes(req, res, next) { 7 | var obj = { items: [ {name_enc: "XJWoMnnOlSF3tFoU4jn4gg==", value_enc: "l0gZvr5oiHds8nQpqe0Kqg==", plain: "Hallo"}, 8 | {name_enc: "XJWoMnnOlSF3tFoU4jn4gg==", value_enc: "l0gZvr5oiHds8nQpqe0Kqg==", plain: "Hallo"}, 9 | {name_enc: "XJWoMnnOlSF3tFoU4jn4gg==", value_enc: "l0gZvr5oiHds8nQpqe0Kqg=="} ], 10 | count: 3}; 11 | res.writeHead(200, {"Content-Type": "application/json"}); 12 | res.end(JSON.stringify(obj)); 13 | next(); 14 | }). 15 | use('/data/query', function getaes(req, res, next) { 16 | var query = url.parse(req.url, true).query; 17 | var obj = {query: query}; 18 | res.writeHead(200, {"Content-Type": "application/json"}); 19 | res.end(JSON.stringify(obj)); 20 | next(); 21 | }). 22 | use('/data/get/des', function getaes(req, res, next) { 23 | var obj = { items: [ {name_enc: "AFx0ylylXKZG3Fp1veuO+g==", value_enc: "kDlxDGGIm2w=", plain: "Hallo"}, 24 | {name_enc: "AFx0ylylXKZG3Fp1veuO+g==", value_enc: "kDlxDGGIm2w=", plain: "Hallo"}, 25 | {name_enc: "AFx0ylylXKZG3Fp1veuO+g==", value_enc: "kDlxDGGIm2w="} ], 26 | count: 3}; 27 | res.writeHead(200, {"Content-Type": "application/json"}); 28 | res.end(JSON.stringify(obj)); 29 | next(); 30 | }). 31 | use('/data/decrypt', function echo(req, res, next) { 32 | res.writeHead(200, {"Content-Type": "application/json_enc"}); 33 | req.pipe(res); 34 | }). 35 | use('/data', function echo(req, res, next) { 36 | res.writeHead(200); 37 | req.pipe(res); 38 | next(); 39 | }). 40 | use(serveStatic(__dirname+'/public')). 41 | listen(port); 42 | -------------------------------------------------------------------------------- /public/test/e2e/plugins/mockAppDes.js: -------------------------------------------------------------------------------- 1 | var myAppDev = angular.module('demoApp-e2e', ['demoApp', 'ngMockE2E']); 2 | 3 | myAppDev.run(["$httpBackend", function ($httpBackend) { 4 | $httpBackend.whenGET('/assets/config').respond(givenEncodedWithFieldNames(), {'content-type': 'application/json;charset=utf-8'}); 5 | $httpBackend.whenGET('/assets/config').respond(givenEncodedWithFieldNames(), {'content-type': 'application/json;charset=utf-8'}); 6 | $httpBackend.whenGET('/assets/config?name_enc=AFx0ylylXKZG3Fp1veuO%2Bg%3D%3D').respond(givenEncodedWithFieldNames(), {'content-type': 'application/json;charset=utf-8'}); 7 | $httpBackend.whenGET('/assets/config?query=H8VtqH0%2Bbsbevunuf6RZoEbEQ3NiyajlumOymJd4vsVOenO4cn32JloP9v5L0yuLP0sryWIAzNA%3D').respond(givenEncodedWithFieldNames(), {'Content-Type': 'application/json;charset=utf-8'}); 8 | $httpBackend.whenPOST('/assets/config', 'O2DvGZe8KL4KqccGVdAz1cJ9f4VIAQLfTBgjJYyLEmZNUdYbuP/jSWc3eaqbJL2tj0iuHbocaW4v9g46mrq1U6if+y4BTrTQrRlMAeNzHQjws+yB0E4yFIEm7WwLBag2').respond({body:'O2DvGZe8KL4KqccGVdAz1cJ9f4VIAQLfTBgjJYyLEmZNUdYbuP/jSWc3eaqbJL2tj0iuHbocaW4v9g46mrq1U6if+y4BTrTQrRlMAeNzHQjws+yB0E4yFIEm7WwLBag2'}, {'content-type': 'application/json;charset=utf-8'}); 9 | $httpBackend.whenPOST('/assets/config', givenProfile()).respond(200); 10 | $httpBackend.whenPOST('/assets/empty').respond(null, {'content-type': 'application/json;charset=utf-8'}); 11 | $httpBackend.whenGET(/partials\/.*/).passThrough(); 12 | }]); 13 | 14 | //given 15 | function givenProfile() { 16 | return { items: [ 17 | {name_enc: "AFx0ylylXKZG3Fp1veuO+g==", value_enc: "kDlxDGGIm2w=", plain: "Hallo"} 18 | ], 19 | count: 1 20 | } 21 | 22 | } 23 | 24 | function givenEncodedWithFieldNames() { 25 | return { items: [ 26 | {name_enc: "AFx0ylylXKZG3Fp1veuO+g==", value_enc: "kDlxDGGIm2w=", plain: "Hallo"}, 27 | {name_enc: "AFx0ylylXKZG3Fp1veuO+g==", value_enc: "kDlxDGGIm2w=", plain: "Hallo"}, 28 | {name_enc: "AFx0ylylXKZG3Fp1veuO+g==", value_enc: "kDlxDGGIm2w="} 29 | ], 30 | count: 3 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /public/test/e2e/plugins/mockAppTripleDes.js: -------------------------------------------------------------------------------- 1 | var myAppDev = angular.module('demoApp-e2e', ['demoApp', 'ngMockE2E']); 2 | 3 | myAppDev.run(["$httpBackend", function ($httpBackend) { 4 | $httpBackend.whenGET('/assets/config').respond(givenEncodedWithFieldNames(), {'content-type': 'application/json;charset=utf-8'}); 5 | $httpBackend.whenGET('/assets/config').respond(givenEncodedWithFieldNames(), {'content-type': 'application/json;charset=utf-8'}); 6 | $httpBackend.whenGET('/assets/config?name_enc=w%2BdTF60Xm%2F26VoKM2gEDTA%3D%3D').respond(givenEncodedWithFieldNames(), {'content-type': 'application/json;charset=utf-8'}); 7 | $httpBackend.whenGET('/assets/config?query=maSq%2B1FVBWfU8QQDSBHRDHeMz526Ar7iFgX4reSHsjfDOv1Kuj7ZRQHzK2XvS3qwffMeGHl7Fo8%3D').respond(givenEncodedWithFieldNames(), {'Content-Type': 'application/json;charset=utf-8'}); 8 | $httpBackend.whenPOST('/assets/config', '2VUSj+1mFXYT6bPgw/PzBQ5fT9WLj0BbGLqKLG6ghQqdyigFM/oMrgEnrZHbn5i1NDkH+8QBwGB7jHDVZIcfIK6bMhbK49N1FmM8Z8QyUWgP0xwxUPV7neQ6QNW5F7Eb').respond({body:'2VUSj+1mFXYT6bPgw/PzBQ5fT9WLj0BbGLqKLG6ghQqdyigFM/oMrgEnrZHbn5i1NDkH+8QBwGB7jHDVZIcfIK6bMhbK49N1FmM8Z8QyUWgP0xwxUPV7neQ6QNW5F7Eb'}, {'content-type': 'application/json;charset=utf-8'}); 9 | $httpBackend.whenPOST('/assets/config', givenProfile()).respond(200); 10 | $httpBackend.whenPOST('/assets/empty').respond(null, {'content-type': 'application/json;charset=utf-8'}); 11 | $httpBackend.whenGET(/partials\/.*/).passThrough(); 12 | }]); 13 | 14 | //given 15 | function givenProfile() { 16 | return { items: [ 17 | {name_enc: "w+dTF60Xm/26VoKM2gEDTA==", value_enc: "QB5mqzB3Zqc=", plain: "Hallo"} 18 | ], 19 | count: 1 20 | } 21 | } 22 | 23 | function givenEncodedWithFieldNames() { 24 | return { items: [ 25 | {name_enc: "w+dTF60Xm/26VoKM2gEDTA==", value_enc: "QB5mqzB3Zqc=", plain: "Hallo"}, 26 | {name_enc: "w+dTF60Xm/26VoKM2gEDTA==", value_enc: "QB5mqzB3Zqc=", plain: "Hallo"}, 27 | {name_enc: "w+dTF60Xm/26VoKM2gEDTA==", value_enc: "QB5mqzB3Zqc="} 28 | ], 29 | count: 3 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /public/example/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Simple Demo App for angularjs-crypto 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 |
41 | 42 | 43 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | angularjs-crypto Demo 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 52 |
53 | 54 | 55 | -------------------------------------------------------------------------------- /wiredep_karma.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 'use strict'; 3 | 4 | var pkg = require('./node_modules/wiredep/package.json'); 5 | var wiredep = require('./node_modules/wiredep'); 6 | var argv = require('./node_modules/wiredep/node_modules/minimist')(process.argv.slice(2)); 7 | var chalk = require('./node_modules/wiredep/node_modules/chalk'); 8 | var fs = require('fs'); 9 | var fileTypes= {js: 10 | { block: /(([\s\t]*)\/\/\s*bower:*(\S*))(\n|\r|.)*?(\/\/\s*endbower)/gi, 11 | detect: {js: /-\s(.+js)/gi}, 12 | replace: {js:'\'{{filePath}}\','} 13 | } 14 | } 15 | 16 | var args = [ 17 | { short: 'h', full: 'help' }, 18 | { short: 'v', full: 'version' }, 19 | { short: 'b', full: 'bowerJson' }, 20 | { short: 'd', full: 'directory' }, 21 | { short: 'e', full: 'exclude' }, 22 | { short: 'i', full: 'ignorePath' }, 23 | { short: 's', full: 'src' } 24 | ]; 25 | 26 | function help() { 27 | console.log(pkg.description); 28 | console.log(''); 29 | console.log('Usage: ' + chalk.cyan('$') + chalk.bold(' wiredep ') + chalk.yellow('[options]')); 30 | console.log(''); 31 | console.log('Options:'); 32 | console.log(' -h, --help # Print usage information'); 33 | console.log(' -v, --version # Print the version'); 34 | console.log(' -b, --bowerJson # Path to `bower.json`'); 35 | console.log(' -d, --directory # Your Bower directory'); 36 | console.log(' -e, --exclude # A path to be excluded'); 37 | console.log(' -i, --ignorePath # A path to be ignored'); 38 | console.log(' -s, --src # Path to your source file'); 39 | console.log(' --dependencies # Include Bower `dependencies`'); 40 | console.log(' --devDependencies # Include Bower `devDependencies`'); 41 | console.log(' --verbose # Print the results of `wiredep`'); 42 | } 43 | 44 | if (argv.v || argv.version) { 45 | console.log(pkg.version); 46 | return; 47 | } 48 | 49 | if (argv.h || argv.help || Object.keys(argv).length === 1) { 50 | help(); 51 | return; 52 | } 53 | 54 | if (!argv.s) { 55 | console.log(chalk.bold.red('> Source file not specified.')); 56 | console.log('Please pass a `--src path/to/source.html` to `wiredep`.'); 57 | return; 58 | } 59 | 60 | if (argv.b || argv.bowerJson) { 61 | try { 62 | argv.bowerJson = JSON.parse(fs.readFileSync(argv.b || argv.bowerJson)); 63 | } catch (e) {} 64 | } 65 | 66 | try { 67 | if (!argv.bowerJson) { 68 | fs.statSync('./bower.json'); 69 | } 70 | } catch (e) { 71 | console.log(chalk.bold.red('> bower.json not found.')); 72 | console.log('Please run `wiredep` from the directory where your `bower.json` file is located.'); 73 | console.log('Alternatively, pass a `--bowerJson path/to/bower.json`.'); 74 | return; 75 | } 76 | argv['fileTypes']=fileTypes 77 | 78 | var results = wiredep(Object.keys(argv).reduce(function (acc, arg) { 79 | args.filter(function (argObj) { 80 | if (argObj.short === arg) { 81 | acc[argObj.full] = argv[arg]; 82 | delete acc[arg]; 83 | } 84 | }); 85 | return acc; 86 | }, argv)); 87 | 88 | if (argv.verbose) { 89 | console.log(results); 90 | } 91 | 92 | 93 | -------------------------------------------------------------------------------- /public/js/controllers.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | function DecodeGetController($scope, Data) { 4 | Data.queryNoCrypt({}, function(response) { 5 | $scope.received=response; 6 | $scope.receivedstr=JSON.stringify($scope.received, null, 4); 7 | }); 8 | Data.get({}, function(response){ 9 | $scope.data=response; 10 | $scope.datastr=JSON.stringify($scope.data, null, 4); 11 | }); 12 | } 13 | 14 | function CustomJsonEncodeController($scope, Data) { 15 | $scope.sendJson = function() { 16 | $scope.dataJson = JSON.parse($scope.data); 17 | $scope.datastr=JSON.stringify($scope.dataJson, null, 4); 18 | Data.save($scope.dataJson, function(response){ 19 | $scope.send = response; 20 | $scope.sendstr=JSON.stringify($scope.send, null, 4); 21 | }) 22 | }; 23 | } 24 | 25 | 26 | function FullJsonEncodeController($scope, Data) { 27 | $scope.sendJson = function() { 28 | $scope.dataJson = JSON.parse($scope.data); 29 | $scope.datastr=JSON.stringify($scope.dataJson, null, 4); 30 | Data.saveFullJson($scope.dataJson, function(response){ 31 | $scope.send = response; 32 | $scope.sendstr=JSON.stringify($scope.send, null, 4); 33 | }) 34 | }; 35 | } 36 | 37 | 38 | function EncodeQueryGetController($scope, Data) { 39 | $scope.plainQueryParam={name_enc:'COMMERZBANK AG'} 40 | Data.queryNoDecrypt({name_enc:'COMMERZBANK AG'}, function(response) { 41 | //store sended query param in scope 42 | $scope.query=response.query; 43 | $scope.data = response; 44 | $scope.datastr=JSON.stringify($scope.data, null, 4); 45 | }); 46 | } 47 | 48 | function EncodeFullQueryGetController($scope, Data) { 49 | $scope.plainQueryParam={name:'COMMERZBANK AG', value:12345, id:12345} 50 | Data.queryFullCrypt({name:'COMMERZBANK AG', value:12345, id:12345}, function(response) { 51 | $scope.query=response.query; 52 | $scope.data = response; 53 | $scope.datastr=JSON.stringify($scope.data, null, 4); 54 | }); 55 | } 56 | 57 | function EncodeBodyPostController($scope, Data) { 58 | $scope.data = { 59 | items: [ 60 | {name_enc: "COMMERZBANK AG", value_enc: "1504.75", plain: "Hallo"} 61 | ], 62 | count: 1 63 | }; 64 | $scope.datastr=JSON.stringify($scope.data, null, 4); 65 | Data.saveEnCrypt($scope.data, function(response){ 66 | $scope.send = response[0]; 67 | }); 68 | } 69 | 70 | function DecodeBodyPostController($scope, Data) { 71 | $scope.data = { 72 | items: [ 73 | {name_enc: "COMMERZBANK AG", value_enc: "1504.75", plain: "Hallo"} 74 | ], 75 | count: 1 76 | }; 77 | $scope.datastr=JSON.stringify($scope.data, null, 4); 78 | Data.saveDeCrypt($scope.data, function(response){ 79 | $scope.received = response; 80 | $scope.receivedstr = JSON.stringify(response, null, 4);; 81 | }); 82 | } 83 | 84 | function EmptyController($scope, Data) { 85 | $scope.received = Data.save(); 86 | $scope.data = Data.get(); 87 | } 88 | 89 | function EncodePostController($scope, Data) { 90 | $scope.data = { 91 | items: [ 92 | {name_enc: "COMMERZBANK AG", value_enc: "1504.75", plain: "Hallo"} 93 | ], 94 | count: 1 95 | }; 96 | $scope.datastr=JSON.stringify($scope.data, null, 4); 97 | $scope.send = { 98 | items: [ 99 | {name_enc: "COMMERZBANK AG", value_enc: "1504.75", plain: "Hallo"} 100 | ], 101 | count: 1 102 | }; 103 | Data.save($scope.send , function(response) { 104 | $scope.sendstr=JSON.stringify($scope.send, null, 4); 105 | }); 106 | } 107 | -------------------------------------------------------------------------------- /karma/karma-shared.conf.js: -------------------------------------------------------------------------------- 1 | // Karma configuration 2 | // Generated on Wed Aug 14 2013 22:33:43 GMT+0200 (CEST) 3 | 4 | module.exports = function (config) { 5 | config.set({ 6 | 7 | // base path, that will be used to resolve files and exclude 8 | basePath: '../', 9 | 10 | 11 | // frameworks to use 12 | frameworks: ['jasmine'], 13 | 14 | 15 | // list of files / patterns to load in the browser 16 | files: [ 17 | // bower:js 18 | 'public/components/jquery/dist/jquery.js', 19 | 'public/components/angular/angular.js', 20 | 'public/components/angular-cookies/angular-cookies.js', 21 | 'public/components/angular-resource/angular-resource.js', 22 | 'public/components/angular-route/angular-route.js', 23 | 'public/components/bootstrap/dist/js/bootstrap.js', 24 | 'public/components/highlightjs/highlight.pack.js', 25 | 'public/components/angular-highlightjs/angular-highlightjs.js', 26 | // endbower 27 | 'https://ajax.googleapis.com/ajax/libs/angularjs/1.3.13/angular-mocks.js', 28 | 'http://crypto-js.googlecode.com/svn/tags/3.1.2/build/rollups/aes.js', 29 | 'http://crypto-js.googlecode.com/svn/tags/3.1.2/build/components/mode-ecb.js', 30 | 'public/js/*.js', 31 | 'public/js/lib/*.js', 32 | 'public/js/cryptojs/rollups/*.js', 33 | 'public/js/cryptojs/components/*.js', 34 | 'public/js/lib/plugins/*.js' 35 | ], 36 | 37 | 38 | // list of files to exclude 39 | exclude: [ 40 | 'public/test/e2e/*.js', 41 | ], 42 | 43 | preprocessors: { 'public/js/*.js': ['coverage'], 44 | 'public/js/lib/*.js': ['coverage'], 45 | 'public/test/unit/*.js': ['coverage'], 46 | 'public/test/e2e/karma/*.coffee': ['coffee'],}, 47 | 48 | 49 | // test results reporter to use 50 | // possible values: 'dots', 'progress', 'junit', 'growl', 'coverage' 51 | // commented reports cause crash 52 | reporters: ['progress', 'dots', 'junit', 'coverage', 'coveralls', 'threshold'], 53 | 54 | thresholdReporter: { 55 | statements: 90, 56 | branches: 60, 57 | functions: 85, 58 | lines: 90 59 | }, 60 | 61 | coverageReporter: { 62 | type: 'lcov', // lcov or lcovonly are required for generating lcov.info files 63 | dir: 'coverage/' 64 | }, 65 | 66 | // web server port 67 | port: 9876, 68 | 69 | 70 | // enable / disable colors in the output (reporters and logs) 71 | colors: true, 72 | 73 | 74 | // level of logging 75 | // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG 76 | logLevel: config.LOG_INFO, 77 | 78 | 79 | // enable / disable watching file and executing tests whenever any file changes 80 | autoWatch: false, 81 | 82 | 83 | // Start these browsers, currently available: 84 | // - Chrome 85 | // - ChromeCanary 86 | // - Firefox 87 | // - Opera 88 | // - Safari (only Mac) 89 | // - PhantomJS 90 | // - IE (only Windows) 91 | browsers: ['Firefox'/*,'Opera', 'Chrome_without_security','Chrome'*/], //Chrome not started in travis ci 92 | 93 | /*customLaunchers: { 94 | Chrome_without_security: { 95 | base: 'Chrome', 96 | flags: ['--disable-web-security'] 97 | } 98 | },*/ 99 | 100 | // If browser does not capture in given timeout [ms], kill it 101 | captureTimeout: 60000, 102 | 103 | 104 | // Continuous Integration mode 105 | // if true, it capture browsers, run tests and exit 106 | singleRun: false, 107 | 108 | proxies: { 109 | '/test/lib/angular/': 'http://localhost:8888/asset/test/lib/angular/' 110 | }, 111 | 112 | urlRoot: '/__karma/', 113 | autoWatch : true 114 | }); 115 | }; 116 | -------------------------------------------------------------------------------- /public/js/lib/angularjs-crypto.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | function missingCryptoJs(shouldCrypt, cfg, q) { 4 | if (!shouldCrypt) return false; 5 | if (cfg.key().length <= 0) return false; 6 | if (typeof(CryptoJS) === 'undefined') return true; 7 | } 8 | var cryptoModule = angular.module('angularjs-crypto', []); 9 | cryptoModule.config(['$httpProvider', function ($httpProvider) { 10 | var interceptor = ['$q', 'cfCryptoHttpInterceptor', function ($q, cfg) { 11 | return { 12 | request: function (request) { 13 | var shouldCrypt = (request.crypt || false); 14 | var pattern = (request.pattern || cfg.pattern); 15 | if (missingCryptoJs(shouldCrypt, cfg, $q)) { 16 | return q.reject('CryptoJS missing'); 17 | } 18 | var data = request.data; 19 | if (shouldCrypt === true) { 20 | if (checkHeader(cfg, request.headers['Content-Type'])) { 21 | log(cfg, "intercept request " + angular.toJson(data)); 22 | if (!data) return $q.reject(request); 23 | encrypt(data, cfg, pattern); 24 | } else if (( typeof( request.params ) != "undefined")) { 25 | encrypt(request.params, cfg, pattern); 26 | } 27 | } else if ((request.fullcryptbody || false)) { 28 | if (!data) return $q.reject(request); 29 | request.data = cfg.plugin.encode(JSON.stringify(data), cfg.key()) 30 | log(cfg, "encode full body " + request.data); 31 | } else if ((request.fullcryptquery || false) && ( typeof( request.params ) != "undefined")) { 32 | log(cfg, "encode full query " + request.params); 33 | request.params = {query:cfg.plugin.encode(JSON.stringify(request.params),cfg.key())} 34 | log(cfg, "encode full query " + request.params); 35 | } 36 | return request; 37 | }, 38 | response: function (response) { 39 | var shouldCrypt = (response.config || false).crypt && defaultVal(response.config.decrypt, true); 40 | var pattern = response.config && response.config.pattern; 41 | pattern = (pattern || cfg.pattern); 42 | if (missingCryptoJs(shouldCrypt, cfg, $q)) { 43 | return q.reject('CryptoJS missing'); 44 | } 45 | if (shouldCrypt == true) { 46 | if (checkHeader(cfg, response.headers()['content-type'])) { 47 | var data = response.data; 48 | log(cfg, "intercept response " + angular.toJson(data)); 49 | if (!data) 50 | return $q.reject(response); 51 | decrypt(data, cfg, pattern); 52 | } 53 | } else if ((response.config.decryptbody || false) && 54 | checkHeader(cfg, response.headers()['content-type'])) { 55 | var data = response.data; 56 | if (!data) return $q.reject(request); 57 | response.data = JSON.parse(cfg.plugin.decode(data, cfg.key())); 58 | log(cfg, "encode full body " + response.data); 59 | } 60 | return response; 61 | } 62 | }; 63 | }] 64 | $httpProvider.interceptors.push(interceptor); 65 | }]); 66 | 67 | cryptoModule.provider('cfCryptoHttpInterceptor', function () { 68 | this.base64Key; 69 | this.base64KeyFunc = function(){return ""}; 70 | this.pattern = "_enc"; 71 | this.logging = false; 72 | this.plugin = new CryptoJSCipher(CryptoJS.mode.ECB, CryptoJS.pad.Pkcs7, CryptoJS.AES); 73 | this.contentHeaderCheck = new ContentHeaderCheck(['application/json', 'application/json_enc']); 74 | this.responseWithQueryParams = true; 75 | 76 | this.$get = function () { 77 | return { 78 | base64Key: this.base64Key, 79 | base64KeyFunc: this.base64KeyFunc, 80 | key: function() { 81 | return this.base64Key || this.base64KeyFunc() 82 | }, 83 | pattern: this.pattern, 84 | plugin: this.plugin, 85 | contentHeaderCheck: this.contentHeaderCheck, 86 | responseWithQueryParams: this.responseWithQueryParams 87 | }; 88 | }; 89 | }); 90 | 91 | function decrypt(data, cfg, pattern) { 92 | if ( typeof(data) !== "undefined" && data !== null ) { 93 | crypt(data, pattern, cfg.plugin.decode, cfg.key()) 94 | } else { 95 | log("data for decryption was null!") 96 | } 97 | 98 | } 99 | function encrypt(data, cfg, pattern) { 100 | if ( typeof(data) !== "undefined" && data !== null ) { 101 | crypt(data, pattern, cfg.plugin.encode, cfg.key()) 102 | } else { 103 | log("data for encryption was null!") 104 | } 105 | } 106 | function crypt(events, pattern, callback, base64Key) { 107 | if(events === "undefined" || events === null) 108 | return; 109 | var keys = Object.keys(events); 110 | for (var i in keys) { 111 | if (pattern !== undefined && events[keys[i]] !== null && events[keys[i]] !== "undefined") { 112 | if (keys[i].endsWith(pattern)) 113 | events[keys[i]] = callback(events[keys[i]], base64Key); 114 | } 115 | if (typeof events[keys[i]] === 'object') 116 | crypt(events[keys[i]], pattern, callback, base64Key) 117 | if (pattern === undefined || pattern === "*") { 118 | events[keys[i]] = callback(events[keys[i]], base64Key); 119 | } 120 | } 121 | } 122 | 123 | function checkHeader(cfg, contentType) { 124 | if(!contentType) { return false; } 125 | return(cfg.contentHeaderCheck.check(contentType)); 126 | } 127 | 128 | String.prototype.beginsWith = function (string) { 129 | return(this.indexOf(string) === 0); 130 | }; 131 | 132 | String.prototype.endsWith = function (str) { 133 | var lastIndex = this.lastIndexOf(str); 134 | return (lastIndex != -1) && (lastIndex + str.length == this.length); 135 | }; 136 | 137 | function defaultVal(val, defaultVal){ 138 | if(typeof val==='undefined'){ 139 | return defaultVal; 140 | }else{ 141 | return val; 142 | } 143 | }; 144 | 145 | function log(cfg, message){ 146 | if (cfg.logging) 147 | console.log(message); 148 | }; 149 | 150 | function ContentHeaderCheck(headerToCrypt) { 151 | var headerToCrypt = headerToCrypt; 152 | return { 153 | check: function(contentType) { 154 | for (var index = 0; index < headerToCrypt.length; index++) { 155 | var result = contentType.beginsWith(headerToCrypt[index]); 156 | if(result) {return true}; 157 | } 158 | return false; 159 | } 160 | } 161 | } 162 | -------------------------------------------------------------------------------- /public/test/unit/controllersSpec.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /* jasmine specs for controllers go here */ 4 | describe('Controllers tests', function () { 5 | 6 | beforeEach(function () { 7 | this.addMatchers({ 8 | toEqualData: function (expected) { 9 | return angular.equals(this.actual, expected); 10 | } 11 | }); 12 | //for jasmine 2.x but protracvter is using jasmine 1 13 | /*jasmine.Expectation.addMatchers({ 14 | toEqualData: function(expected) { 15 | return { 16 | compare: function (actual, expected) { 17 | var pass = angular.equals(actual, expected); 18 | var what = pass ? 'bad' : 'good'; 19 | return { 20 | pass: pass, 21 | message: 'Expected data ' + JSON.stringify(actual, null, 4) + ' to be a '+ JSON.stringify(expected, null, 4) +' .' 22 | }; 23 | } 24 | }; 25 | } 26 | })*/ 27 | }); 28 | 29 | 30 | 31 | 32 | //TODO is uncommented because check if cryptoHttpInterceptor is registered as http interceptor not working because it is added as anonoums function because that was the only way i know to inject the cfCryptoHttpInterceptor config provider 33 | /*describe('config: with module callback in beforeEach', function () { 34 | 35 | var httpProvider; 36 | 37 | beforeEach(module('demoApp', function ($httpProvider) { 38 | console.log('BEGIN: module callback'); 39 | httpProvider = $httpProvider; 40 | console.log('END: module callback'); 41 | })); 42 | 43 | it('should have added cryptoHttpInterceptor as http interceptor (inject calls module callback before run test)', inject(function () { 44 | console.log('BEGIN: it test'); 45 | expect(httpProvider.interceptors).toContain('cryptoHttpInterceptor'); 46 | console.log('END: it test'); 47 | })); 48 | 49 | });*/ 50 | 51 | beforeEach(module('demoApp')); 52 | 53 | 54 | describe('decode GET response', function () { 55 | var scope, $httpBackend, rootScope; 56 | 57 | beforeEach(inject(function (_$httpBackend_, $rootScope, $controller) { 58 | $httpBackend = _$httpBackend_; 59 | rootScope = $rootScope; 60 | scope = $rootScope.$new(); 61 | $controller(DecodeGetController, {$scope: scope}); 62 | })); 63 | 64 | it('decode simple json by field name that ends with _enc', function () { 65 | $httpBackend.expectGET('/data/get/aes').respond(200, {items: [ 66 | {name_enc: "XJWoMnnOlSF3tFoU4jn4gg==", value_enc: "l0gZvr5oiHds8nQpqe0Kqg==", plain: "Hallo"} 67 | ], 68 | count: 1 69 | }, {'Content-Type': 'application/json;charset=utf-8'}); 70 | $httpBackend.expectGET('/data/get/aes').respond(200, {items: [ 71 | {name_enc: "XJWoMnnOlSF3tFoU4jn4gg==", value_enc: "l0gZvr5oiHds8nQpqe0Kqg==", plain: "Hallo"} 72 | ], 73 | count: 1 74 | }, {'Content-Type': 'application/json;charset=utf-8'}); 75 | rootScope.$digest(); 76 | $httpBackend.flush(); 77 | expect(scope.data).toEqualData({items: [ 78 | { name_enc: 'COMMERZBANK AG', value_enc: '1504.75', plain: 'Hallo' } 79 | ], count: 1}); 80 | expect(scope.received).toEqualData({items: [ 81 | {name_enc: "XJWoMnnOlSF3tFoU4jn4gg==", value_enc: "l0gZvr5oiHds8nQpqe0Kqg==", plain: "Hallo"} 82 | ], 83 | count: 1 84 | }); 85 | }); 86 | 87 | it('decode complex json by field name that ends with _enc', function () { 88 | $httpBackend.expectGET('/data/get/aes').respond(200, 89 | { items: [ 90 | {name_enc: "XJWoMnnOlSF3tFoU4jn4gg==", value_enc: "l0gZvr5oiHds8nQpqe0Kqg==", plain: "Hallo"}, 91 | {name_enc: "XJWoMnnOlSF3tFoU4jn4gg==", value_enc: "l0gZvr5oiHds8nQpqe0Kqg==", plain: "Hallo"}, 92 | {name_enc: "XJWoMnnOlSF3tFoU4jn4gg==", value_enc: "l0gZvr5oiHds8nQpqe0Kqg=="} 93 | ], 94 | count: 3 95 | }, {'Content-Type': 'application/json;charset=utf-8'} 96 | ); 97 | $httpBackend.expectGET('/data/get/aes').respond(200, 98 | { items: [ 99 | {name_enc: "XJWoMnnOlSF3tFoU4jn4gg==", value_enc: "l0gZvr5oiHds8nQpqe0Kqg==", plain: "Hallo"}, 100 | {name_enc: "XJWoMnnOlSF3tFoU4jn4gg==", value_enc: "l0gZvr5oiHds8nQpqe0Kqg==", plain: "Hallo"}, 101 | {name_enc: "XJWoMnnOlSF3tFoU4jn4gg==", value_enc: "l0gZvr5oiHds8nQpqe0Kqg=="} 102 | ], 103 | count: 3 104 | }, {'Content-Type': 'application/json;charset=utf-8'} 105 | ); 106 | rootScope.$digest(); 107 | $httpBackend.flush(); 108 | expect(scope.data).toEqualData({items: [ 109 | { name_enc: 'COMMERZBANK AG', value_enc: '1504.75', plain: 'Hallo' }, 110 | { name_enc: 'COMMERZBANK AG', value_enc: '1504.75', plain: 'Hallo' }, 111 | { name_enc: 'COMMERZBANK AG', value_enc: '1504.75'} 112 | ], count: 3}); 113 | expect(scope.received).toEqualData({ items: [ 114 | {name_enc: "XJWoMnnOlSF3tFoU4jn4gg==", value_enc: "l0gZvr5oiHds8nQpqe0Kqg==", plain: "Hallo"}, 115 | {name_enc: "XJWoMnnOlSF3tFoU4jn4gg==", value_enc: "l0gZvr5oiHds8nQpqe0Kqg==", plain: "Hallo"}, 116 | {name_enc: "XJWoMnnOlSF3tFoU4jn4gg==", value_enc: "l0gZvr5oiHds8nQpqe0Kqg=="} 117 | ], 118 | count: 3 119 | }); 120 | }); 121 | }); 122 | 123 | describe('encode POST,PUT request', function () { 124 | var scope, $httpBackend, rootScope; 125 | 126 | beforeEach(inject(function (_$httpBackend_, $rootScope, $controller) { 127 | $httpBackend = _$httpBackend_; 128 | rootScope = $rootScope; 129 | scope = $rootScope.$new(); 130 | $controller(EncodePostController, {$scope: scope}); 131 | })); 132 | 133 | it('encode simple json post request all fields that end with _enc', function () { 134 | $httpBackend.expectPOST('/data', { items: [ 135 | {name_enc: "XJWoMnnOlSF3tFoU4jn4gg==", value_enc: "l0gZvr5oiHds8nQpqe0Kqg==", plain: "Hallo"} 136 | ], 137 | count: 1 138 | }).respond(200); 139 | rootScope.$digest(); 140 | $httpBackend.flush(); 141 | expect(scope.send).toEqualData({items: [ 142 | {name_enc: "XJWoMnnOlSF3tFoU4jn4gg==", value_enc: "l0gZvr5oiHds8nQpqe0Kqg==", plain: "Hallo"} 143 | ], 144 | count: 1 145 | }); 146 | }); 147 | }); 148 | 149 | describe('empty http responses', function () { 150 | var scope, $httpBackend, rootScope; 151 | 152 | beforeEach(inject(function (_$httpBackend_, $rootScope, $controller) { 153 | $httpBackend = _$httpBackend_; 154 | rootScope = $rootScope; 155 | scope = $rootScope.$new(); 156 | $controller(EmptyController, {$scope: scope}); 157 | })); 158 | 159 | it('reject request with empty data and set content type to application/json', function () { 160 | // post request is requested because of empty request data (body) 161 | /*$httpBackend.whenPOST('/assets/empty').respond(200, null,{'content-type': 'application/json;charset=utf-8'});*/ 162 | $httpBackend.whenGET('/data/get/aes').respond(200, null,{'content-type': 'application/json;charset=utf-8'}); 163 | rootScope.$digest(); 164 | $httpBackend.flush(); 165 | expect(scope.data).toEqualData({}); 166 | expect(scope.received).toEqualData({}); 167 | }); 168 | 169 | it('reject promise by empty response which should be decrypted by service configuration', function () { 170 | $httpBackend.whenGET('/data/get/aes').respond(200, null,{'content-type': 'application/json;charset=utf-8'}); 171 | rootScope.$digest(); 172 | $httpBackend.flush(); 173 | expect(scope.data).toEqualData({}); 174 | expect(scope.received).toEqualData({}); 175 | }); 176 | }); 177 | 178 | describe('encode query parameters', function () { 179 | var scope, $httpBackend, rootScope; 180 | 181 | beforeEach(inject(function (_$httpBackend_, $rootScope, $controller) { 182 | $httpBackend = _$httpBackend_; 183 | rootScope = $rootScope; 184 | scope = $rootScope.$new(); 185 | $controller(EncodeQueryGetController, {$scope: scope}); 186 | })); 187 | 188 | it('encode query param by field name pattern', function () { 189 | $httpBackend.expectGET('/data/query?name_enc=XJWoMnnOlSF3tFoU4jn4gg%3D%3D').respond(200, { 190 | query: "name_enc=XJWoMnnOlSF3tFoU4jn4gg==" 191 | }, 192 | {'Content-Type': 'application/json;charset=utf-8'} 193 | ); 194 | rootScope.$digest(); 195 | $httpBackend.flush(); 196 | expect(scope.query).toEqualData('name_enc=XJWoMnnOlSF3tFoU4jn4gg=='); 197 | }); 198 | }); 199 | 200 | describe('encode complete request body', function () { 201 | var scope, $httpBackend, rootScope; 202 | 203 | beforeEach(inject(function (_$httpBackend_, $rootScope, $controller) { 204 | $httpBackend = _$httpBackend_; 205 | rootScope = $rootScope; 206 | scope = $rootScope.$new(); 207 | $controller(EncodeBodyPostController, {$scope: scope}); 208 | })); 209 | 210 | it('encode post request body', function () { 211 | $httpBackend.expectPOST('/data','7fF8WOaj2HNvqhnOgvCNWFlxbNFX3N2Fi13ueR/Fe5kT5/pZGp1oVUw+ZYIgv7ST/Ke4+F5/8JXQI87/mpHVlNF6UrYEHrqAnj0gewtcwQ20lf+Kc4aSaXwJN8XJuNYy').respond(200); 212 | rootScope.$digest(); 213 | $httpBackend.flush(); 214 | }); 215 | }); 216 | 217 | 218 | describe('decode complete response body', function () { 219 | var scope, $httpBackend, rootScope; 220 | 221 | beforeEach(inject(function (_$httpBackend_, $rootScope, $controller) { 222 | $httpBackend = _$httpBackend_; 223 | rootScope = $rootScope; 224 | scope = $rootScope.$new(); 225 | $controller(DecodeBodyPostController, {$scope: scope}); 226 | })); 227 | 228 | it('decode post request body', function () { 229 | $httpBackend.expectPOST('/data/decrypt','7fF8WOaj2HNvqhnOgvCNWFlxbNFX3N2Fi13ueR/Fe5kT5/pZGp1oVUw+ZYIgv7ST/Ke4+F5/8JXQI87/mpHVlNF6UrYEHrqAnj0gewtcwQ20lf+Kc4aSaXwJN8XJuNYy').respond(200, '7fF8WOaj2HNvqhnOgvCNWFlxbNFX3N2Fi13ueR/Fe5kT5/pZGp1oVUw+ZYIgv7ST/Ke4+F5/8JXQI87/mpHVlNF6UrYEHrqAnj0gewtcwQ20lf+Kc4aSaXwJN8XJuNYy', {'Content-Type': 'application/json_enc'}); 230 | rootScope.$digest(); 231 | $httpBackend.flush(); 232 | expect(scope.received).toEqualData({ 233 | items: [ 234 | {name_enc: "COMMERZBANK AG", value_enc: "1504.75", plain: "Hallo"} 235 | ], 236 | count: 1 237 | }); 238 | }); 239 | }); 240 | 241 | describe('encode complete request query params', function () { 242 | var scope, $httpBackend, rootScope; 243 | 244 | beforeEach(inject(function (_$httpBackend_, $rootScope, $controller) { 245 | $httpBackend = _$httpBackend_; 246 | rootScope = $rootScope; 247 | scope = $rootScope.$new(); 248 | $controller(EncodeFullQueryGetController, {$scope: scope}); 249 | })); 250 | 251 | it('encode complete get request query params', function () { 252 | $httpBackend.expectGET('/data/query?query=WZM2hwPXWx4%2B7SbaJpUPrh6KZl7c4lqZ%2F67En5tJy8DGTjW%2BmxDV0g8t2UtDklW4f1Ec%2Fmr6hPf2K6V%2BoE%2F21A%3D%3D').respond(200, { 253 | query: "WZM2hwPXWx4+7SbaJpUPrh6KZl7c4lqZ/67En5tJy8DGTjW+mxDV0g8t2UtDklW4f1Ec/mr6hPf2K6V+oE/21A==" 254 | }, 255 | {'Content-Type': 'application/json;charset=utf-8'} 256 | ); 257 | rootScope.$digest(); 258 | $httpBackend.flush(); 259 | expect(scope.query).toEqualData('WZM2hwPXWx4+7SbaJpUPrh6KZl7c4lqZ/67En5tJy8DGTjW+mxDV0g8t2UtDklW4f1Ec/mr6hPf2K6V+oE/21A=='); 260 | }); 261 | }); 262 | 263 | }); 264 | -------------------------------------------------------------------------------- /public/js/cryptojs/rollups/aes.js: -------------------------------------------------------------------------------- 1 | /* 2 | CryptoJS v3.1.2 3 | code.google.com/p/crypto-js 4 | (c) 2009-2013 by Jeff Mott. All rights reserved. 5 | code.google.com/p/crypto-js/wiki/License 6 | */ 7 | var CryptoJS=CryptoJS||function(u,p){var d={},l=d.lib={},s=function(){},t=l.Base={extend:function(a){s.prototype=this;var c=new s;a&&c.mixIn(a);c.hasOwnProperty("init")||(c.init=function(){c.$super.init.apply(this,arguments)});c.init.prototype=c;c.$super=this;return c},create:function(){var a=this.extend();a.init.apply(a,arguments);return a},init:function(){},mixIn:function(a){for(var c in a)a.hasOwnProperty(c)&&(this[c]=a[c]);a.hasOwnProperty("toString")&&(this.toString=a.toString)},clone:function(){return this.init.prototype.extend(this)}}, 8 | r=l.WordArray=t.extend({init:function(a,c){a=this.words=a||[];this.sigBytes=c!=p?c:4*a.length},toString:function(a){return(a||v).stringify(this)},concat:function(a){var c=this.words,e=a.words,j=this.sigBytes;a=a.sigBytes;this.clamp();if(j%4)for(var k=0;k>>2]|=(e[k>>>2]>>>24-8*(k%4)&255)<<24-8*((j+k)%4);else if(65535>>2]=e[k>>>2];else c.push.apply(c,e);this.sigBytes+=a;return this},clamp:function(){var a=this.words,c=this.sigBytes;a[c>>>2]&=4294967295<< 9 | 32-8*(c%4);a.length=u.ceil(c/4)},clone:function(){var a=t.clone.call(this);a.words=this.words.slice(0);return a},random:function(a){for(var c=[],e=0;e>>2]>>>24-8*(j%4)&255;e.push((k>>>4).toString(16));e.push((k&15).toString(16))}return e.join("")},parse:function(a){for(var c=a.length,e=[],j=0;j>>3]|=parseInt(a.substr(j, 10 | 2),16)<<24-4*(j%8);return new r.init(e,c/2)}},b=w.Latin1={stringify:function(a){var c=a.words;a=a.sigBytes;for(var e=[],j=0;j>>2]>>>24-8*(j%4)&255));return e.join("")},parse:function(a){for(var c=a.length,e=[],j=0;j>>2]|=(a.charCodeAt(j)&255)<<24-8*(j%4);return new r.init(e,c)}},x=w.Utf8={stringify:function(a){try{return decodeURIComponent(escape(b.stringify(a)))}catch(c){throw Error("Malformed UTF-8 data");}},parse:function(a){return b.parse(unescape(encodeURIComponent(a)))}}, 11 | q=l.BufferedBlockAlgorithm=t.extend({reset:function(){this._data=new r.init;this._nDataBytes=0},_append:function(a){"string"==typeof a&&(a=x.parse(a));this._data.concat(a);this._nDataBytes+=a.sigBytes},_process:function(a){var c=this._data,e=c.words,j=c.sigBytes,k=this.blockSize,b=j/(4*k),b=a?u.ceil(b):u.max((b|0)-this._minBufferSize,0);a=b*k;j=u.min(4*a,j);if(a){for(var q=0;q>>2]>>>24-8*(r%4)&255)<<16|(l[r+1>>>2]>>>24-8*((r+1)%4)&255)<<8|l[r+2>>>2]>>>24-8*((r+2)%4)&255,v=0;4>v&&r+0.75*v>>6*(3-v)&63));if(l=t.charAt(64))for(;d.length%4;)d.push(l);return d.join("")},parse:function(d){var l=d.length,s=this._map,t=s.charAt(64);t&&(t=d.indexOf(t),-1!=t&&(l=t));for(var t=[],r=0,w=0;w< 15 | l;w++)if(w%4){var v=s.indexOf(d.charAt(w-1))<<2*(w%4),b=s.indexOf(d.charAt(w))>>>6-2*(w%4);t[r>>>2]|=(v|b)<<24-8*(r%4);r++}return p.create(t,r)},_map:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="}})(); 16 | (function(u){function p(b,n,a,c,e,j,k){b=b+(n&a|~n&c)+e+k;return(b<>>32-j)+n}function d(b,n,a,c,e,j,k){b=b+(n&c|a&~c)+e+k;return(b<>>32-j)+n}function l(b,n,a,c,e,j,k){b=b+(n^a^c)+e+k;return(b<>>32-j)+n}function s(b,n,a,c,e,j,k){b=b+(a^(n|~c))+e+k;return(b<>>32-j)+n}for(var t=CryptoJS,r=t.lib,w=r.WordArray,v=r.Hasher,r=t.algo,b=[],x=0;64>x;x++)b[x]=4294967296*u.abs(u.sin(x+1))|0;r=r.MD5=v.extend({_doReset:function(){this._hash=new w.init([1732584193,4023233417,2562383102,271733878])}, 17 | _doProcessBlock:function(q,n){for(var a=0;16>a;a++){var c=n+a,e=q[c];q[c]=(e<<8|e>>>24)&16711935|(e<<24|e>>>8)&4278255360}var a=this._hash.words,c=q[n+0],e=q[n+1],j=q[n+2],k=q[n+3],z=q[n+4],r=q[n+5],t=q[n+6],w=q[n+7],v=q[n+8],A=q[n+9],B=q[n+10],C=q[n+11],u=q[n+12],D=q[n+13],E=q[n+14],x=q[n+15],f=a[0],m=a[1],g=a[2],h=a[3],f=p(f,m,g,h,c,7,b[0]),h=p(h,f,m,g,e,12,b[1]),g=p(g,h,f,m,j,17,b[2]),m=p(m,g,h,f,k,22,b[3]),f=p(f,m,g,h,z,7,b[4]),h=p(h,f,m,g,r,12,b[5]),g=p(g,h,f,m,t,17,b[6]),m=p(m,g,h,f,w,22,b[7]), 18 | f=p(f,m,g,h,v,7,b[8]),h=p(h,f,m,g,A,12,b[9]),g=p(g,h,f,m,B,17,b[10]),m=p(m,g,h,f,C,22,b[11]),f=p(f,m,g,h,u,7,b[12]),h=p(h,f,m,g,D,12,b[13]),g=p(g,h,f,m,E,17,b[14]),m=p(m,g,h,f,x,22,b[15]),f=d(f,m,g,h,e,5,b[16]),h=d(h,f,m,g,t,9,b[17]),g=d(g,h,f,m,C,14,b[18]),m=d(m,g,h,f,c,20,b[19]),f=d(f,m,g,h,r,5,b[20]),h=d(h,f,m,g,B,9,b[21]),g=d(g,h,f,m,x,14,b[22]),m=d(m,g,h,f,z,20,b[23]),f=d(f,m,g,h,A,5,b[24]),h=d(h,f,m,g,E,9,b[25]),g=d(g,h,f,m,k,14,b[26]),m=d(m,g,h,f,v,20,b[27]),f=d(f,m,g,h,D,5,b[28]),h=d(h,f, 19 | m,g,j,9,b[29]),g=d(g,h,f,m,w,14,b[30]),m=d(m,g,h,f,u,20,b[31]),f=l(f,m,g,h,r,4,b[32]),h=l(h,f,m,g,v,11,b[33]),g=l(g,h,f,m,C,16,b[34]),m=l(m,g,h,f,E,23,b[35]),f=l(f,m,g,h,e,4,b[36]),h=l(h,f,m,g,z,11,b[37]),g=l(g,h,f,m,w,16,b[38]),m=l(m,g,h,f,B,23,b[39]),f=l(f,m,g,h,D,4,b[40]),h=l(h,f,m,g,c,11,b[41]),g=l(g,h,f,m,k,16,b[42]),m=l(m,g,h,f,t,23,b[43]),f=l(f,m,g,h,A,4,b[44]),h=l(h,f,m,g,u,11,b[45]),g=l(g,h,f,m,x,16,b[46]),m=l(m,g,h,f,j,23,b[47]),f=s(f,m,g,h,c,6,b[48]),h=s(h,f,m,g,w,10,b[49]),g=s(g,h,f,m, 20 | E,15,b[50]),m=s(m,g,h,f,r,21,b[51]),f=s(f,m,g,h,u,6,b[52]),h=s(h,f,m,g,k,10,b[53]),g=s(g,h,f,m,B,15,b[54]),m=s(m,g,h,f,e,21,b[55]),f=s(f,m,g,h,v,6,b[56]),h=s(h,f,m,g,x,10,b[57]),g=s(g,h,f,m,t,15,b[58]),m=s(m,g,h,f,D,21,b[59]),f=s(f,m,g,h,z,6,b[60]),h=s(h,f,m,g,C,10,b[61]),g=s(g,h,f,m,j,15,b[62]),m=s(m,g,h,f,A,21,b[63]);a[0]=a[0]+f|0;a[1]=a[1]+m|0;a[2]=a[2]+g|0;a[3]=a[3]+h|0},_doFinalize:function(){var b=this._data,n=b.words,a=8*this._nDataBytes,c=8*b.sigBytes;n[c>>>5]|=128<<24-c%32;var e=u.floor(a/ 21 | 4294967296);n[(c+64>>>9<<4)+15]=(e<<8|e>>>24)&16711935|(e<<24|e>>>8)&4278255360;n[(c+64>>>9<<4)+14]=(a<<8|a>>>24)&16711935|(a<<24|a>>>8)&4278255360;b.sigBytes=4*(n.length+1);this._process();b=this._hash;n=b.words;for(a=0;4>a;a++)c=n[a],n[a]=(c<<8|c>>>24)&16711935|(c<<24|c>>>8)&4278255360;return b},clone:function(){var b=v.clone.call(this);b._hash=this._hash.clone();return b}});t.MD5=v._createHelper(r);t.HmacMD5=v._createHmacHelper(r)})(Math); 22 | (function(){var u=CryptoJS,p=u.lib,d=p.Base,l=p.WordArray,p=u.algo,s=p.EvpKDF=d.extend({cfg:d.extend({keySize:4,hasher:p.MD5,iterations:1}),init:function(d){this.cfg=this.cfg.extend(d)},compute:function(d,r){for(var p=this.cfg,s=p.hasher.create(),b=l.create(),u=b.words,q=p.keySize,p=p.iterations;u.length>>2]&255}};d.BlockCipher=v.extend({cfg:v.cfg.extend({mode:b,padding:q}),reset:function(){v.reset.call(this);var a=this.cfg,b=a.iv,a=a.mode;if(this._xformMode==this._ENC_XFORM_MODE)var c=a.createEncryptor;else c=a.createDecryptor,this._minBufferSize=1;this._mode=c.call(a, 28 | this,b&&b.words)},_doProcessBlock:function(a,b){this._mode.processBlock(a,b)},_doFinalize:function(){var a=this.cfg.padding;if(this._xformMode==this._ENC_XFORM_MODE){a.pad(this._data,this.blockSize);var b=this._process(!0)}else b=this._process(!0),a.unpad(b);return b},blockSize:4});var n=d.CipherParams=l.extend({init:function(a){this.mixIn(a)},toString:function(a){return(a||this.formatter).stringify(this)}}),b=(p.format={}).OpenSSL={stringify:function(a){var b=a.ciphertext;a=a.salt;return(a?s.create([1398893684, 29 | 1701076831]).concat(a).concat(b):b).toString(r)},parse:function(a){a=r.parse(a);var b=a.words;if(1398893684==b[0]&&1701076831==b[1]){var c=s.create(b.slice(2,4));b.splice(0,4);a.sigBytes-=16}return n.create({ciphertext:a,salt:c})}},a=d.SerializableCipher=l.extend({cfg:l.extend({format:b}),encrypt:function(a,b,c,d){d=this.cfg.extend(d);var l=a.createEncryptor(c,d);b=l.finalize(b);l=l.cfg;return n.create({ciphertext:b,key:c,iv:l.iv,algorithm:a,mode:l.mode,padding:l.padding,blockSize:a.blockSize,formatter:d.format})}, 30 | decrypt:function(a,b,c,d){d=this.cfg.extend(d);b=this._parse(b,d.format);return a.createDecryptor(c,d).finalize(b.ciphertext)},_parse:function(a,b){return"string"==typeof a?b.parse(a,this):a}}),p=(p.kdf={}).OpenSSL={execute:function(a,b,c,d){d||(d=s.random(8));a=w.create({keySize:b+c}).compute(a,d);c=s.create(a.words.slice(b),4*c);a.sigBytes=4*b;return n.create({key:a,iv:c,salt:d})}},c=d.PasswordBasedCipher=a.extend({cfg:a.cfg.extend({kdf:p}),encrypt:function(b,c,d,l){l=this.cfg.extend(l);d=l.kdf.execute(d, 31 | b.keySize,b.ivSize);l.iv=d.iv;b=a.encrypt.call(this,b,c,d.key,l);b.mixIn(d);return b},decrypt:function(b,c,d,l){l=this.cfg.extend(l);c=this._parse(c,l.format);d=l.kdf.execute(d,b.keySize,b.ivSize,c.salt);l.iv=d.iv;return a.decrypt.call(this,b,c,d.key,l)}})}(); 32 | (function(){for(var u=CryptoJS,p=u.lib.BlockCipher,d=u.algo,l=[],s=[],t=[],r=[],w=[],v=[],b=[],x=[],q=[],n=[],a=[],c=0;256>c;c++)a[c]=128>c?c<<1:c<<1^283;for(var e=0,j=0,c=0;256>c;c++){var k=j^j<<1^j<<2^j<<3^j<<4,k=k>>>8^k&255^99;l[e]=k;s[k]=e;var z=a[e],F=a[z],G=a[F],y=257*a[k]^16843008*k;t[e]=y<<24|y>>>8;r[e]=y<<16|y>>>16;w[e]=y<<8|y>>>24;v[e]=y;y=16843009*G^65537*F^257*z^16843008*e;b[k]=y<<24|y>>>8;x[k]=y<<16|y>>>16;q[k]=y<<8|y>>>24;n[k]=y;e?(e=z^a[a[a[G^z]]],j^=a[a[j]]):e=j=1}var H=[0,1,2,4,8, 33 | 16,32,64,128,27,54],d=d.AES=p.extend({_doReset:function(){for(var a=this._key,c=a.words,d=a.sigBytes/4,a=4*((this._nRounds=d+6)+1),e=this._keySchedule=[],j=0;j>>24]<<24|l[k>>>16&255]<<16|l[k>>>8&255]<<8|l[k&255]):(k=k<<8|k>>>24,k=l[k>>>24]<<24|l[k>>>16&255]<<16|l[k>>>8&255]<<8|l[k&255],k^=H[j/d|0]<<24);e[j]=e[j-d]^k}c=this._invKeySchedule=[];for(d=0;dd||4>=j?k:b[l[k>>>24]]^x[l[k>>>16&255]]^q[l[k>>> 34 | 8&255]]^n[l[k&255]]},encryptBlock:function(a,b){this._doCryptBlock(a,b,this._keySchedule,t,r,w,v,l)},decryptBlock:function(a,c){var d=a[c+1];a[c+1]=a[c+3];a[c+3]=d;this._doCryptBlock(a,c,this._invKeySchedule,b,x,q,n,s);d=a[c+1];a[c+1]=a[c+3];a[c+3]=d},_doCryptBlock:function(a,b,c,d,e,j,l,f){for(var m=this._nRounds,g=a[b]^c[0],h=a[b+1]^c[1],k=a[b+2]^c[2],n=a[b+3]^c[3],p=4,r=1;r>>24]^e[h>>>16&255]^j[k>>>8&255]^l[n&255]^c[p++],s=d[h>>>24]^e[k>>>16&255]^j[n>>>8&255]^l[g&255]^c[p++],t= 35 | d[k>>>24]^e[n>>>16&255]^j[g>>>8&255]^l[h&255]^c[p++],n=d[n>>>24]^e[g>>>16&255]^j[h>>>8&255]^l[k&255]^c[p++],g=q,h=s,k=t;q=(f[g>>>24]<<24|f[h>>>16&255]<<16|f[k>>>8&255]<<8|f[n&255])^c[p++];s=(f[h>>>24]<<24|f[k>>>16&255]<<16|f[n>>>8&255]<<8|f[g&255])^c[p++];t=(f[k>>>24]<<24|f[n>>>16&255]<<16|f[g>>>8&255]<<8|f[h&255])^c[p++];n=(f[n>>>24]<<24|f[g>>>16&255]<<16|f[h>>>8&255]<<8|f[k&255])^c[p++];a[b]=q;a[b+1]=s;a[b+2]=t;a[b+3]=n},keySize:8});u.AES=p._createHelper(d)})(); 36 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [angularjs-crypto](http://ngmodules.org/modules/angularjs-crypto) 2 | ================== 3 | [![Build Status](https://travis-ci.org/pussinboots/angularjs-crypto.svg?branch=master)](https://travis-ci.org/pussinboots/angularjs-crypto) 4 | [![Coverage Status](https://img.shields.io/coveralls/pussinboots/angularjs-crypto.svg)](https://coveralls.io/r/pussinboots/angularjs-crypto?branch=master) 5 | [![Dependencies](https://david-dm.org/pussinboots/angularjs-crypto.png)](https://david-dm.org/pussinboots/angularjs-crypto) 6 | [![Heroku](http://heroku-badge.herokuapp.com/?app=angularjs-crypto&style=flat)](https://angularjs-crypto.herokuapp.com/) 7 | [![Unit Tests](https://unitcover.herokuapp.com/api/pussinboots/angularjs-crypto/badge)](https://unitcover.herokuapp.com/#/builds/pussinboots/angularjs-crypto/builds) 8 | [![Codio](https://d2g7ua7d94r3fl.cloudfront.net/assets/images/8aa866ae.codio_logo.png)](https://codio.com/pussinboots/angularjs-crypto) 9 | 10 | [![Gitter chat](https://badges.gitter.im/pussinboots/angularjs-crypto.png)](https://gitter.im/pussinboots/angularjs-crypto) 11 | 12 | [![Test Results](http://unitcover.herokuapp.com/api/pussinboots/angularjs-crypto/testsuites/badge)](http://unitcover.herokuapp.com/#/builds/pussinboots/angularjs-crypto/builds) 13 | 14 | AngularJS Module that integrate cryptography functionality offers from the [crypto-js](https://code.google.com/p/crypto-js/) project for all http requests and response. 15 | 16 | Inprogress update to the new angularjs version but before protractor migration. 17 | 18 | ## Demo Application 19 | 20 | There is demo application that use this library to demonstrate the client side encryption and storing that encrypted data on a server. Retrieve this data back and decrypt on the client side to display the data. 21 | 22 | [Demo](https://secure-notes.herokuapp.com) 23 | 24 | [Source Code](https://github.com/pussinboots/secure-notes) 25 | 26 | 27 | ## Versions 28 | 29 | Actual there are two versions one for angularjs 1.2 and one for angularjs 1.3. 30 | - angularjs 1.2 use the 1.2 branch it is tested with the latest 1.2.28 version 31 | - angularjs 1.3 use the master branch it is tested with 1.3.13 version 32 | 33 | ## Feature Requests 34 | 35 | - support public private key encryption/decryption maybe by integrate this javascript [library](https://github.com/travist/jsencrypt) 36 | - encrypt / decrypt binary data like images (setup a working example and maybe support it directly with angularjs-crypto) [example image encryption](http://alicebobandmallory.com/articles/2010/10/14/encrypt-images-in-javascript) 37 | 38 | ## Code 39 | [anuglarjs-crypto.js](https://github.com/pussinboots/angularjs-crypto/blob/master/public/js/lib/angularjs-crypto.js) 40 | 41 | Dependencies 42 | ------------ 43 | - [AngularJS 1.1.4 + ](http://angularjs.org/) (tested with 1.1.4, 1.2.16, 1.2.28, 1.3.13) 44 | - [Crypto-js 3.1.2 AES modul](https://raw.githubusercontent.com/pussinboots/angularjs-crypto/master/public/js/cryptojs/rollups/aes.js) 45 | - [Crypto-js 3.1.2 ecb mode](https://raw.githubusercontent.com/pussinboots/angularjs-crypto/master/public/js/cryptojs/components/mode-ecb.js) 46 | 47 | ## Bower Versions 48 | 49 | - 0.0.3 : support all ciphers that are supported by CryptoJS 50 | - 0.0.4 : support decryption of encoded reponse body 51 | - 1.2.0 : use it for 1.14 + and 1.2.x version of angularjs 52 | - 1.3.0 : use for angularjs 1.3.x 53 | 54 | ## Development 55 | 56 | To simplify the checkout and the setup of a full development environment with all needed dependencies the [vagrant-git](https://github.com/pussinboots/vagrant-git) project is used. 57 | 58 | But before we can use the [vagrant-git](https://github.com/pussinboots/vagrant-git) project first install all [reequieremnts](https://github.com/pussinboots/vagrant-git#requirements). It is implemented as nodejs application. Than you can install the [vagrant-git](https://github.com/pussinboots/vagrant-git) project follow this [instruction](https://github.com/pussinboots/vagrant-git#install). Usage turorial can be found [here](https://github.com/pussinboots/vagrant-git#usage). 59 | 60 | To setup a development vagrant box for this project execute the command below. 61 | ```bash 62 | vgit --repo pussinboots/angularjs-crypto 63 | ``` 64 | It will checkpout the vagrant runtime repo and this project itslef. 65 | 66 | On Windows without ssh client 67 | ```bash 68 | vgit --g https --repo pussinboots/angularjs-crypto 69 | ``` 70 | That use https instead of ssh protocol. The ssh protocol is the default used protocol. So the first execution will take a while to download the vagrant [base box](https://vagrantcloud.com/pussinboots/boxes/ubuntu-truly) defined in the Vagrantfile. Than it install the defined dependencies see below. When the login screen appear login with vagrant/vagrant than you have a ready to use development environment for that project up and running. The project will be checkout to the vagrant shared folder so that the Host and Guest operating systems can access the git clone. 71 | 72 | The vagrant-git configuration is defined in the [.vagrant.yml](.vagrant.yml) file. The configuration will be explained on the next line the [general explanetion](https://github.com/pussinboots/vagrant-git#project-configuration). 73 | ```yml 74 | repo: 75 | - pussinboots/vagrant-devel 76 | folder: /vagrant/project/angularjs-crypto 77 | deps: 78 | - sublime3 79 | - nodejs 80 | ``` 81 | 82 | repo: defined the following github repo like https://github.com/pussinboots/vagrant-devel as the vagrant runtime repo where the [Vagrant configuration](https://github.com/pussinboots/vagrant-devel/blob/master/Vagrantfile) is placed that will be used for that project. 83 | 84 | folder: is only information for the Developer that will pe display before vagrant startup so that he or sher knows where the angularjs-crypto project root folder can be found. 85 | 86 | deps: defined the dependencies to be installed during vagrant provision. 87 | 88 | 89 | 90 | ## Install (bower) 91 | 92 | * bower install angularjs-crypto 93 | * js file is under the [bower_components/]angularjs-crypto/public/js/lib/angularjs-crypto.js 94 | ```html 95 | 96 | 97 | 98 | 99 | ``` 100 | 101 | ## Install (manual) 102 | 103 | * download [js file](https://github.com/pussinboots/angularjs-crypto/blob/master/public/js/lib/angularjs-crypto.js) 104 | * download [js plugin file](https://github.com/pussinboots/angularjs-crypto/blob/master/public/js/lib/plugins/CryptoJSCipher.js) 105 | * download [cryptojs aes](https://raw.githubusercontent.com/pussinboots/angularjs-crypto/master/public/js/cryptojs/rollups/aes.js) 106 | * download [crypto mode-ecb](https://raw.githubusercontent.com/pussinboots/angularjs-crypto/master/public/js/cryptojs/components/mode-ecb.js) 107 | * added javascript file to your app html file 108 | ```html 109 | 110 | 111 | 112 | 113 | ``` 114 | 115 | ## Usage 116 | 117 | * add modul dependency ('angularjs-crypto') to angular 118 | ```js 119 | var demoApp = angular.module('demoApp', ['services', 'angularjs-crypto']); 120 | ``` 121 | 122 | Example Service Definition 123 | 124 | * configure the http request for automatic decryption/encryption detection by setting property crypt:true 125 | 126 | ```js 127 | 'use strict'; 128 | 129 | angular.module('services', ['ngResource'], function ($provide) { 130 | $provide.factory('Data', function ($resource) { 131 | return $resource('/assets/config', {}, { 132 | query: {method: 'GET', isArray: false, crypt: true}, 133 | queryNoCrypt: {method: 'GET'}, 134 | save: {method: 'POST', params: {}, crypt: true}, 135 | saveNoCrypt: {method: 'POST', params: {}} 136 | }); 137 | }); 138 | }); 139 | ``` 140 | 141 | * configure base64Key aes key for decryption/encryption 142 | 143 | ```js 144 | demoApp.run(['cfCryptoHttpInterceptor', function(cfCryptoHttpInterceptor) { 145 | cfCryptoHttpInterceptor.base64Key = "16rdKQfqN3L4TY7YktgxBw=="; 146 | }]) 147 | ``` 148 | 149 | That's done now all json fields that end with the pattern (default: '_enc') will be encoded in requests and decoded in responses. 150 | 151 | Issues 152 | ------------- 153 | - Report at the github [issue tracker](https://github.com/pussinboots/angularjs-crypto/issues) 154 | 155 | Todos 156 | ------------- 157 | * configurable error handling strict or elegant mode 158 | * support for http ajax calls missing only ng resource calls are supported (under investigation) 159 | * add support of encrypted cookies that are decrypted on server side 160 | 161 | Features 162 | ------------- 163 | * implements ciphers offered by the [crypto-js](https://code.google.com/p/crypto-js/) project 164 | * AES 165 | * DES 166 | * Triple DES 167 | * Rabbit 168 | * RC4, RC4Drop 169 | * configuration the cipher algorithm to use (aes is configured as default) (done [see](https://github.com/pussinboots/angularjs-crypto/blob/master/README.md#set-own-plugin-implementation-for-encoding-and-decoding))) 170 | * configuration a function that return the aes secret key to use for encryption/decryption 171 | * encoding of complete query and body for requests 172 | * encoding of query parameter fields that end with the pattern 173 | * configuration of encode/decode function so that you can plugin in your own implementation 174 | * configuration of the aes secret key to use for encryption/decryption 175 | * configuration of the field name pattern which determinate which fields will be encrypted/decrypted 176 | * aes encryption/decryption of http json requests and responses 177 | * only with mode [ECB](http://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Electronic_codebook_.28ECB.29) 178 | * only with padding [Pkcs7](http://en.wikipedia.org/wiki/Padding_(cryptography)#PKCS7) 179 | * automatic detection of encryption/decryption for json fields based on the naming rule all fields end with pattern (default: :enc) as it comes 180 | * reponse then decrypt 181 | * request then encrypt 182 | * only requests / responses of Content-Type: 'application/json;charset=utf-8' will be processed other types will skip crypt processing include auto detection 183 | 184 | Configuration 185 | ------------- 186 | 187 | #### Set the base64Key for aes encryption/decryption 188 | 189 | ```js 190 | var demoApp = angular.module('demoApp', ['angularjs-crypto']); 191 | demoApp.run(['cfCryptoHttpInterceptor', function(cfCryptoHttpInterceptor) { 192 | cfCryptoHttpInterceptor.base64Key = "16rdKQfqN3L4TY7YktgxBw=="; 193 | }]) 194 | ``` 195 | 196 | #### Set the field name pattern 197 | 198 | ```js 199 | var demoApp = angular.module('demoApp', ['angularjs-crypto']); 200 | demoApp.run(['cfCryptoHttpInterceptor', function(cfCryptoHttpInterceptor) { 201 | cfCryptoHttpInterceptor.pattern = "_enc"; //that is the default value 202 | }]) 203 | ``` 204 | 205 | #### Set own plugin implementation for encoding and decoding 206 | 207 | This make it now possible to simple add other CryptoJs cipher implementations like DES or even other crypto libraries as well. If i find the time than i will add at least the supported cipher from CryptoJs. An example implementation that use Crypto AES can be found [here](https://github.com/pussinboots/angularjs-crypto/blob/master/public/js/lib/CryptoJSPlugin.js) 208 | ```js 209 | var demoApp = angular.module('demoApp', ['angularjs-crypto']); 210 | demoApp.run(['cfCryptoHttpInterceptor', function(cfCryptoHttpInterceptor) { 211 | cfCryptoHttpInterceptor.plugin = { 212 | encode: function(plainValue, base64Key) { 213 | return plainValue; 214 | }, 215 | decode : function(encryptedValue, base64Key) { 216 | return encryptedValue; 217 | } 218 | }; 219 | }]) 220 | ``` 221 | 222 | #### configure the cipher algorithm to use 223 | 224 | ```js 225 | demoApp.run(['cfCryptoHttpInterceptor', function(cfCryptoHttpInterceptor) { 226 | cfCryptoHttpInterceptor.plugin = new CryptoJSCipher(CryptoJS.mode.ECB, CryptoJS.pad.Pkcs7, CryptoJS.DES) 227 | }) 228 | ``` 229 | 230 | - availabe ciphers that are supported by [CryptoJS](https://code.google.com/p/crypto-js/#Ciphers) 231 | ```js 232 | demoApp.run(['cfCryptoHttpInterceptor', function(cfCryptoHttpInterceptor) { 233 | cfCryptoHttpInterceptor.plugin = new CryptoJSCipher(CryptoJS.mode.ECB, CryptoJS.pad.Pkcs7, CryptoJS.AES) 234 | cfCryptoHttpInterceptor.plugin = new CryptoJSCipher(CryptoJS.mode.ECB, CryptoJS.pad.Pkcs7, CryptoJS.DES) 235 | cfCryptoHttpInterceptor.plugin = new CryptoJSCipher(CryptoJS.mode.ECB, CryptoJS.pad.Pkcs7, CryptoJS.TripleDES) 236 | cfCryptoHttpInterceptor.plugin = new CryptoJSCipher(CryptoJS.mode.ECB, CryptoJS.pad.Pkcs7, CryptoJS.Rabbit) 237 | cfCryptoHttpInterceptor.plugin = new CryptoJSCipher(CryptoJS.mode.ECB, CryptoJS.pad.Pkcs7, CryptoJS.RC4) 238 | cfCryptoHttpInterceptor.plugin = new CryptoJSCipher(CryptoJS.mode.ECB, CryptoJS.pad.Pkcs7, CryptoJS.RC4Drop) 239 | }) 240 | ``` 241 | #### Configure the Content-Type header for encryption/decryption 242 | ``` 243 | demoApp.run(['cfCryptoHttpInterceptor', function(cfCryptoHttpInterceptor) { 244 | cfCryptoHttpInterceptor.contentHeaderCheck = new ContentHeaderCheck(['application/json', 'application/json_enc']); 245 | } 246 | ``` 247 | The default configured Content-Type is shown above. That means only for request's and responses 248 | that have one of the aboved Content-Type will be enrypted/decrypted. For example if you perform a request with the Content-Type : 'text/plain'. This request will be skipped for encryption even if shouldCrypt is set to true. 249 | 250 | There is also the possibilities to implement your own ContentHeaderCheck that for example always return 251 | true. Like that own below. 252 | 253 | ``` 254 | function ContentTypeDoesntMatterCheck() { 255 | return { 256 | check: function(contentType) { 257 | return true; 258 | } 259 | } 260 | } 261 | ``` 262 | To use the new implemented ContentHeaderCheck apply following configuration code. 263 | ``` 264 | demoApp.run(['cfCryptoHttpInterceptor', function(cfCryptoHttpInterceptor) { 265 | cfCryptoHttpInterceptor.contentHeaderCheck = new ContentTypeDoesntMatterCheck(); 266 | } 267 | ``` 268 | 269 | #### Activate console logging 270 | 271 | ```js 272 | var demoApp = angular.module('demoApp', ['angularjs-crypto']); 273 | demoApp.run(['cfCryptoHttpInterceptor', function(cfCryptoHttpInterceptor) { 274 | cfCryptoHttpInterceptor.logging = true; //the default value is false. True will log the decrypted and the encrypted values to the console. 275 | }]) 276 | ``` 277 | 278 | #### Complete encoding of query parameter 279 | 280 | ```js 281 | $provide.factory('Data', function ($resource) { 282 | return $resource('/assets/config', {}, { 283 | queryFullCrypt: {method: 'GET', isArray: false, fullcryptquery:true} 284 | }); 285 | }); 286 | ``` 287 | 288 | #### Complete encoding of body 289 | 290 | ```js 291 | $provide.factory('Data', function ($resource) { 292 | return $resource('/assets/config', {}, { 293 | saveFullCrypt: {method: 'POST', fullcryptbody:true} 294 | }); 295 | }); 296 | ``` 297 | 298 | ##Example 299 | 300 | #### Key Example 301 | 302 | Change the base64Key locally by read it from the rootScope. 303 | 304 | ```js 305 | var demoApp = angular.module('demoApp', ['angularjs-crypto']); 306 | demoApp.run(function(cfCryptoHttpInterceptor, $rootScope) { 307 | cfCryptoHttpInterceptor.base64Key = $rootScope.base64Key; 308 | cfCryptoHttpInterceptor.pattern = "_enc"; //default value but for a better understanding it is also defined here 309 | }) 310 | ``` 311 | 312 | #### Key Example Function 313 | 314 | Define a function which will be used to get the key for encryption/decryption is called 315 | for every encryption/decryption process. 316 | 317 | ```js 318 | var demoApp = angular.module('demoApp', ['angularjs-crypto']); 319 | demoApp.run(function(cfCryptoHttpInterceptor, $rootScope) { 320 | cfCryptoHttpInterceptor.base64KeyFunc = function() { 321 | return $rootScope.base64Key; 322 | } 323 | }) 324 | ``` 325 | 326 | With this html snippet you can edit the key to use only locally. 327 | 328 | ```html 329 | 330 | ``` 331 | 332 | Example App 333 | ------------- 334 | 335 | Setup a simple example app that use mongodb as persistence layer for storing encrypted data. 336 | 337 | [Github](https://github.com/pussinboots/secure-notes) 338 | 339 | [Live](https://secure-notes.herokuapp.com) 340 | 341 | Demo 342 | ------------- 343 | 344 | live 345 | ------ 346 | 347 | The http calls are mocked with angular-mock. 348 | 349 | [Http Get Example](http://angularjs-crypto.herokuapp.com/#/get) 350 | 351 | [Http Post Example](http://angularjs-crypto.herokuapp.com/#/post) 352 | 353 | [Http Get query parameters encoding ](http://angularjs-crypto.herokuapp.com/#/query) 354 | 355 | [Complete query encoding](http://angularjs-crypto.herokuapp.com/#/fullquery) 356 | 357 | [Complete body encoding](http://angularjs-crypto.herokuapp.com/#/fullbody) 358 | 359 | [Change base64Key Example](http://angularjs-crypto.herokuapp.com/#/key) 360 | 361 | local 362 | ------ 363 | 364 | Two ways to run the demo app local one with play or second with nodejs. 365 | 366 | Dependencies 367 | * play 2.2.3 (optional) 368 | * nodejs 0.10.28 369 | * [karma-test runner](http://karma-runner.github.io/0.12/intro/installation.html) 370 | 371 | Start it with play 372 | 373 | play run 374 | 375 | Then go to 376 | * [Get Example](http://localhost:9000/#/get) 377 | * [Post Example](http://localhost:9000/#/post) 378 | * [Http Get query parameters encoding ](http://localhost:9000/#/query) 379 | * [Change base64Key Example](http://localhost:9000/#/key) 380 | * [Complete query encoding](http://localhost:9000/#/fullquery) 381 | * [Complete body encoding](http://localhost:9000/#/fullbody) 382 | 383 | Start it with nodejs 384 | 385 | node server.js 386 | 387 | 388 | Then go to 389 | * [Get Example](http://localhost:9000/#/get) 390 | * [Post Example](http://localhost:9000/#/post) 391 | * [Http Get query parameters encoding ](http://localhost:9000/#/query) 392 | * [Change base64Key Example](http://localhost:9000/#/key) 393 | * [Complete query encoding](http://localhost:9000/#/fullquery) 394 | * [Complete body encoding](http://localhost:9000/#/fullbody) 395 | 396 | Or run the karma test local with 397 | 398 | npm test 399 | 400 | Description 401 | ------------- 402 | 403 | This angularjs module is part of the [bankapp](https://github.com/pussinboots/bankapp). 404 | The idea is to store encrypted data in a backend and decode it on the client side so that the backend 405 | doesn't know what kind of data it stores only the angularjs client and the storage process know the 406 | plain data. 407 | 408 | If you have question or want to take of the development than write me a mail at pussinboots666@googlemail.com. 409 | 410 | It is a very young project but with the support of wide open source tools like karma and travis it 411 | will flow soon i hope. 412 | 413 | License 414 | -------------- 415 | 416 | angularjs-crypto is released under the [MIT License](http://opensource.org/licenses/MIT). 417 | --------------------------------------------------------------------------------