SubtleCrypto.wrapKey usage: can exportKey but not wrapKey? - rsa

I'm trying to wrap an RSA private key using an AES-256 key-wrapping key, using the SubtleCrypto API. I've managed to make the RSA keys and key-wrapping AES key (plus another symmetric AES key) using generateKey, but wrapKey fails on the RSA private key.
I can successfully export and then import the RSA private key, and I can successfully wrap and unwrap a general-purpose AES key. But I get a "data provide to an operation does not meet requirements" error when trying to wrap the RSA private key, and I don't understand what I'm doing wrong.
HTML file for testing:
<!DOCTYPE html>
<html lang="eng-US">
<head>
<meta charset="UTF-8">
<title>Test WebCrypto.subtle</title>
</head>
<body>
<h1>Test WebCrypto.subtle Functions</h1>
<div id="output">
</div>
<script type="text/javascript" src="https://code.jquery.com/jquery-3.4.1.js"></script>
<script type="text/javascript">
function TestCrypto( ) {
$('#output').append( 'Starting test...<br/>' );
let info = {};
window.test_result = info;
let seq = crypto.subtle.generateKey( { name: 'RSA-OAEP',
modulusLength: 1024,
publicExponent: new Uint8Array( [ 1, 0, 1 ] ),
hash: 'SHA-256' },
true, // extractable
[ 'encrypt', 'decrypt' ] )
.then( (rsaKey) =>
{
$('#output').append( 'Created RSA key<br/>' );
info.RSA = rsaKey;
return crypto.subtle.generateKey( { name: 'AES-GCM',
length: 256 },
true,
[ 'encrypt', 'decrypt' ] )
} )
.then( (symKey) =>
{
$('#output').append( 'Created symmetric AES key<br/>' );
info.AES = symKey;
return crypto.subtle.generateKey( { name: 'AES-KW',
length: 256 },
true,
[ 'wrapKey', 'unwrapKey' ] )
} )
.then( (kek) =>
{
$('#output').append( 'Created key-encryption AES key<br/>' );
info.KEK = kek;
return crypto.subtle.exportKey( 'pkcs8',
info.RSA.privateKey );
} )
.then( (expPrivKey) =>
{
$('#output').append( 'Exported RSA private key<br/>' );
info.exportedPrivateKey = expPrivKey;
return crypto.subtle.importKey( 'pkcs8',
info.exportedPrivateKey,
{ name: 'RSA-OAEP',
hash: 'SHA-256' },
true,
[ 'decrypt', 'unwrapKey' ] );
} )
.then( (impPrivKey) =>
{
$('#output').append( 'Imported RSA private key<br/>' );
info.importedPrivateKey = impPrivKey;
/* Wrapping & unwrapping an AES key works...
return crypto.subtle.wrapKey( 'raw',
info.AES,
info.KEK,
'AES-KW' );
*/
/* Wrapping & unwrapping an RSA key doesn't work... */
return crypto.subtle.wrapKey( 'pkcs8',
info.RSA.privateKey,
info.KEK,
'AES-KW' );
} )
.then( (wrappedKey) =>
{
$('#output').append( 'Wrapped a key<br/>' );
info.wrappedKey = wrappedKey;
/*
return crypto.subtle.unwrapKey( 'raw',
info.wrappedKey,
info.KEK,
'AES-KW',
{ name: 'AES-GCM',
length: 256 },
true,
[ 'encrypt', 'decrypt' ] );
*/
return crypto.subtle.unwrapKey( 'pkcs8',
info.wrappedPrivateKey,
info.KEK,
'AES-KW',
{ name: 'RSA-OAEP',
// These items shouldn't be needed, but don't help
// even if you add them.
// modulusLength: 1024,
// publicExponent: new Uint8Array( [ 1, 0, 1 ] ),
hash: 'SHA-256' },
true,
[ 'decrypt', 'unwrapKey' ] );
} )
.then( (unwrappedKey) =>
{
$('#output').append( 'Unwrapped the key<br/>' );
info.unwrappedKey = unwrappedKey;
$('#output').append( 'Testing complete, check console for results<br/>' );
console.log( info );
window.test_result = info;
return info;
} )
.catch( (e) =>
{
$('#output').append( 'Key testing failed<br/>' )
.append( e.toString( ) )
.append( '<br/>' );
} );
}
$(document).ready( TestCrypto );
</script>
</body>
</html>

After a lot of testing and re-reading docs, I found the section that solves this problem:
One advantage of using AES-KW over another AES mode such as AES-GCM is
that AES-KW does not require an initialization vector. To use
AES-KW, the input must be a multiple of 64 bits.

Related

My dateFormat is not working for Flatpickr in Mobile

I am using Datepicker of Flatpickr and I have set the date format and it is working fine in desktop but in mobile it is not working properly.
This is my code that I added in functions.php:
add_action( 'wp_footer', function() {
?>
<script type="text/javascript">
jQuery( window ).load( function( $ ){
var limitFlatPicker;
var afterTwoDays;
var afterEightDays;
limitFlatPicker = limitFlatPicker || {};
limitFlatPicker = {
defaultSettings: {
selector: '.flatpickr-input',
minDate: true,
maxDate: true,
},
settings: {},
init: function( options ) {
this.settings = jQuery.extend( this.defaultSettings, options );
if ( this.settings.minDate || this.settings.maxDate ) {
this.waitForFlatpicker( this.callback );
}
},
waitForFlatpicker: function( callback ) {
if ( typeof window.flatpickr !== 'function' ) {
setTimeout( function() { limitFlatPicker.waitForFlatpicker( callback ) }, 100 );
}
callback();
},
modifyPicker: function( picker, settings ) {
flatpickr( picker ).set( settings );
},
callback: function() {
var self;
self = limitFlatPicker;
jQuery( self.settings.selector ).each( function() {
var picker;
picker = jQuery( this )[0],
pickerSettings = {};
if ( self.settings.minDate ) {
pickerSettings.minDate = self.settings.minDate;
}
if ( self.settings.maxDate ) {
pickerSettings['maxDate'] = self.settings.maxDate;
}
if ( self.settings.dateFormat ) {
pickerSettings.dateFormat = self.settings.dateFormat;
}
self.modifyPicker( picker, pickerSettings );
} );
}
}
limitFlatPicker.init({
minDate: new Date(),
selector: '#form-field-form_field_date',
dateFormat: 'm-d-Y',
});
} );
</script>
<?php
},11);
The dateFormat: 'm-d-Y' is working fine in desktop and in mobile, it is not showing this dateformat.
Any help is much appreciated.

Chain Actions in an Effect ngrx v8

I want to chain effects with the latest syntax of ngrx. I've searched and found this question on stackoverflow but it has old syntax.
This is the current effect:
export class DeleteCommentEffect {
deleteComment$ = createEffect(() =>
this.actions$.pipe(
ofType(DeletingComment),
mergeMap((action) => this.commentService.deleteComment(action.dossierId, action.commentId)
.pipe(
map((statusCode: number) => {
return DeleteCommentSuccess({ statusCode });
}),
catchError((error: HttpErrorResponse) => {
return of(DeleteCommentError({ error }));
})
))
)
);
constructor(
private actions$: Actions,
private commentService: DBCommentService) {
}
}
I want to chain this effect after successfully delete a comment.
export class GetCommentEffects {
getComment$ = createEffect(() =>
this.actions$.pipe(
ofType(GettingComment),
mergeMap(action =>
this.commentService.getAllComments(action.dossierId).pipe(
map((comments: Comment[]) => {
return GetCommentSuccess({comments});
}),
catchError((error: HttpErrorResponse) => {
return of(GetCommentError({error}));
})
))
)
);
constructor(
private actions$: Actions,
private commentService: DBCommentService
) {}
}
I've searched in ngrx docs but it seems like it does not mention about how to chain effects.
Create an effect that listens for DeleteCommentSuccess action that dispatches GettingComment.
deleteCommentSuccess$ = createEffect(() =>
this.actions$.pipe(
ofType(DeleteCommentSuccess),
map(() => CommentActions.GettingComments())
)
);

Update values in a pair of text fields

I have a form component:
import React from 'react'
import Relay from 'react-relay'
import { browserHistory } from 'react-router'
import MenuItem from 'material-ui/MenuItem'
import TextField from 'material-ui/TextField'
import CreateTransformationSetMutation from '../mutations/CreateTransformationSetMutation'
class CreateTransformationSetDialog extends React.Component {
componentWillMount() {
this.props.setOnDialog({
onSubmit: this.onSubmit,
title: 'Create and Apply Transformation Set'
})
}
initial_state = {
targetTableName: '',
transformations: this.props.viewer.version.columns.edges.map(edge => edge.node).map(column => {
return {
targetColumnName: column.name,
ruleExpression: '{{' + column.name + '}}'
}
})
}
state = this.initial_state
onSubmit = () => {
const onSuccess = (response) => {
browserHistory.push('/table')
}
const onFailure = () => {}
Relay.Store.commitUpdate(
new CreateTransformationSetMutation(
{
viewer: this.props.viewer,
version: this.props.viewer.version,
targetTableName: this.state.targetTableName,
transformations: JSON.stringify({transformations: this.state.transformations}),
}
),
{ onSuccess: onSuccess }
)
}
handleTableNameChange = (e) => {
this.setState({
targetTableName: e.target.value
})
}
handleTransChange = (e) => {
////what should go here////
}
render() {
return (
<div>
<TextField
floatingLabelText="Table Name"
value={this.state.targetTableName}
onChange={this.handleTableNameChange}
/>
<br />
{
this.props.viewer.version.columns.edges.map((edge) => edge.node).map((column, i) =>
<div key={column.id}>
<TextField
name="targetColumnName"
floatingLabelText="Target Column"
value={this.state.transformations[i].targetColumnName}
onChange={this.handleTransChange}
style={{ margin: 12 }}
/>
<TextField
name="ruleExpression"
floatingLabelText="Rule to Apply"
value={this.state.transformations[i].ruleExpression}
onChange={this.handleTransChange}
style={{ margin: 12 }}
/>
</div>
)
}
</div>
)
}
}
export default Relay.createContainer(CreateTransformationSetDialog, {
fragments: {
viewer: () => Relay.QL`
fragment on Viewer {
${CreateTransformationSetMutation.getFragment('viewer')}
version(id: $modalEntityId) #include(if: $modalShow) {
${CreateTransformationSetMutation.getFragment('version')}
id
name
columns(first: 100) {
edges {
node {
id
name
}
}
}
}
}
`
},
initialVariables: {
modalEntityId: '',
modalName: '',
modalShow: true,
},
prepareVariables: ({ modalEntityId, modalName }) => {
return {
modalEntityId,
modalName,
modalShow: modalName === 'createTransformationSet'
}
}
})
Each input is a set of two material-ui TextFields that have a default value obtained from this.state.transformations. However, I am trying to update the values in these fields and I am not having any luck.
The default state of transformations will look something like this:
transformations: [
{targetColumnName: 'ID', ruleExpression: '{{ID}}'},
{targetColumnName: 'First Name', ruleExpression: '{{FirstName}}'},
{targetColumnName: 'Last Name', ruleExpression: '{{LastName}}'}
]
And I want to be able to update it so that the state can change, for example to:
transformations: [
{targetColumnName: 'ID', ruleExpression: '{{ID}}'},
{targetColumnName: 'First Name', ruleExpression: '{{FirstName}}'},
{targetColumnName: 'Percentage', ruleExpression: '{{Percentage/100}}'}
]
The form is built using Relay but that is not relevant to this question.
Any help with this would be much appreciated.
Thanks for your time.
I had a similar problem and instead I put the value in value attribute, uses defaultValue='some-value' so that it can be mutated and changed.
It seems that what you are trying to do is not possible to protect from XSS (Cross-site scripting)
Write like this:
<TextField
name="targetColumnName"
floatingLabelText="Target Column"
defaultValue={this.state.transformations[i].targetColumnName} {/* change from value to defaultValue */}
onChange={this.handleTransChange}
style={{ margin: 12 }}
/>

Getting values from form input groups

I have a group of form inputs that are produced like so:
Please see UPDATE 2 below for full component.
So, if there are three columns then three of this group will be shown in the form. I am trying to extract the data from these inputs but I only need the ids. How can I extract the column id from the TextField?
Also, I need to get the data (i.e. the ids) per group so that they appear in an array:
transformations: [{columnId: 1, ruleId: 4}, {columnId: 2, ruleId: 2}, {columnId:3 , ruleId: 1}]
These are just example values, the main problem as I mentioned, is that I'm not sure how to extract the value of the columnId from the first input. I'm also struggling with getting the multiple sets of data.
Any help with this problem would be much appreciated.
Thanks for your time.
UPDATE:
handleRuleChange looks like this:
handleRuleChange = (e, index, value) => {
this.setState({
ruleId: value
})
}
UPDATE 2:
Here is the component:
import React from 'react'
import Relay from 'react-relay'
import { browserHistory } from 'react-router'
import SelectField from 'material-ui/SelectField'
import MenuItem from 'material-ui/MenuItem'
import TextField from 'material-ui/TextField'
import CreateTransformationSetMutation from '../mutations/CreateTransformationSetMutation'
class CreateTransformationSetDialog extends React.Component {
componentWillMount() {
this.props.setOnDialog({
onSubmit: this.onSubmit,
title: 'Create and Apply Transformation Set'
})
}
initial_state = {
targetTableName: '',
ruleId: 'UnVsZTo1',
}
state = this.initial_state
onSubmit = () => {
const onSuccess = (response) => {
console.log(response)
browserHistory.push('/table')
}
const onFailure = () => {}
Relay.Store.commitUpdate(
new CreateTransformationSetMutation(
{
viewer: this.props.viewer,
version: this.props.viewer.version,
targetTableName: this.state.targetTableName,
transformations: ///this is where I need to get the values///,
}
),
{ onSuccess: onSuccess }
)
}
handleTextChange = (e) => {
this.setState({
targetTableName: e.target.value
})
}
handleRuleChange = (e, index, value) => {
this.setState({
ruleId: value
})
}
render() {
return (
<div>
<TextField
floatingLabelText="Table Name"
value={this.state.targetTableName}
onChange={this.handleTextChange}
/>
<br />
{
this.props.viewer.version.columns.edges.map((edge) => edge.node).map((column) =>
<div key={column.id}>
<TextField
id={column.id}
floatingLabelText="Column"
value={column.name}
disabled={true}
style={{ margin: 12 }}
/>
<SelectField
floatingLabelText="Select a Rule"
value={this.state.ruleId}
onChange={this.handleRuleChange}
style={{ margin: 12 }}
>
{
this.props.viewer.allRules.edges.map(edge => edge.node).map(rule =>
<MenuItem
key={rule.id}
value={rule.id}
primaryText={rule.name}
/>
)
}
</SelectField>
</div>
)
}
</div>
)
}
}
export default Relay.createContainer(CreateTransformationSetDialog, {
fragments: {
viewer: () => Relay.QL`
fragment on Viewer {
${CreateTransformationSetMutation.getFragment('viewer')}
version(id: $modalEntityId) #include(if: $modalShow) {
${CreateTransformationSetMutation.getFragment('version')}
id
name
columns(first: 100) {
edges {
node {
id
name
}
}
}
}
allRules(first: 100) {
edges {
node {
id
name
}
}
}
}
`
},
initialVariables: {
modalEntityId: '',
modalName: '',
modalShow: true,
},
prepareVariables: ({ modalEntityId, modalName }) => {
return {
modalEntityId,
modalName,
modalShow: modalName === 'createTransformationSet'
}
}
})
It is using Relay but that isn't connected to the question, just need to extract the data from the inputs into the transformations array.
This can meet your requirement. Most of code will be understandable. feel free to ask for queries.
class CreateTransformationSetDialog extends React.Component {
componentWillMount() {
this.props.setOnDialog({
onSubmit: this.onSubmit,
title: 'Create and Apply Transformation Set'
})
}
initial_state = {
targetTableName: '',
transformations: [];
ruleId:'UnVsZTo1' //default values for all rules
}
state = this.initial_state
onSubmit = () => {
const onSuccess = (response) => {
console.log(response)
browserHistory.push('/table')
}
const onFailure = () => {}
Relay.Store.commitUpdate(
new CreateTransformationSetMutation(
{
viewer: this.props.viewer,
version: this.props.viewer.version,
targetTableName: this.state.targetTableName,
transformations: this.state.transformations,
}
),
{ onSuccess: onSuccess }
)
}
handleTextChange = (e) => {
this.setState({
targetTableName: e.target.value
})
}
handleRuleChange = (index, ruleId, columnId) => { //TODO: make use of index if needed
let transformations = this.state.transformations;
const isInStateWithIndex = transformations.findIndex((el) => el.columnId === columnId);
if(isInStateWithIndex > -1){
transformations[isInStateWithIndex].ruleId = ruleId; //changed rule
}else{
transformations.push({columnId: columnId, ruleId: ruleId}); //new column added to state.
}
this.setState({
transformations: transformations
}); //do with es6 spread operators to avoid immutability if any
}
render() {
return (
<div>
<TextField
floatingLabelText="Table Name"
value={this.state.targetTableName}
onChange={this.handleTextChange}
/>
<br />
{
this.props.viewer.version.columns.edges.map((edge) => edge.node).map((column) =>
<div key={column.id}>
<TextField
id={column.id}
floatingLabelText="Column"
value={column.name}
disabled={true}
style={{ margin: 12 }}
/>
<SelectField
floatingLabelText="Select a Rule"
value={this.state.ruleId}
onChange={(e, index, value) => this.handleRuleChange(index, value, column.id )}
style={{ margin: 12 }}
>
{
this.props.viewer.allRules.edges.map(edge => edge.node).map(rule =>
<MenuItem
key={rule.id}
value={rule.id}
primaryText={rule.name}
/>
)
}
</SelectField>
</div>
)
}
</div>
)
}
}
Maintaining the state for transformations in state with dynamically created columns.

Angularjs, search form, factory: Button doesn't work

I have a typical form-with-query-editor and search button im my Angularjs-app. However, clicking the search-button doesn't work. If I initially open the form with the table, the service works. But not when clicking the search button. The code is as follows:
HTML vlist.html:
<input ng-model="nachname" type="text" id="nachname" name="nachname" class="search-query" />
<button ng-click="search()" type="submit" class="btn btn-primary">Search</button>
...
<tr ng-repeat="pers in personen">
<td>{{pers.nachname}}</td>
</tr>
...
Controller:
var app = angular.module( 'cdemoApp', [ 'cdemo.services' ] );
app.config( ['$routeProvider', function( $routeProvider ) {
$routeProvider.
when( '/vlist', {
controller: 'VListCtrl',
resolve: {
personlistdto: function( VListLoader ) {
return VListLoader();
}
},
templateUrl : 'app/view/vlist.html'
} ).otherwise( { redirectTo: '/' } );
} ] );
app.controller( 'VListCtrl', [ '$scope', 'personlistdto',
function( $scope, personlistdto ) {
$scope.search = function(){
$scope.personen = personlistdto.aaData;
$scope.iTotalRecords = personlistdto.iTotalRecords;
};
$scope.search();
}]);
Service:
var services = angular.module( 'cdemo.services', [ 'ngResource' ] );
services.factory( 'Vers', [ '$resource',
function find( $resource ) {
return $resource( '/cdemo/rest/vers/ajs/:id',
{ id: '#id', isArray: false }
);
} ] );
services.factory( 'VListLoader', [ 'Vers', '$q',
function( Vers, $q ) {
console.log('Vloader1');
var find = function find() {
var delay = $q.defer();
Vers.get( function( personlistdto ) {
delay.resolve( personlistdto );
}, function() {
delay.reject( 'Nix fetch' );
} );
return delay.promise;
};
return find;
} ] );
Any idea how I can get the button searching (including fields/parameters) - because nothing happens when clicking the button? Thanks for an answer.
I got it working by changing the controller like this:
app.controller( 'VListCtrl', [ '$scope', 'personlistdto', 'VListLoader',
function( $scope, personlistdto, VListLoader ) {
$scope.personlistdto = personlistdto;
$scope.searchFactory = VListLoader;
$scope.search = function( ){
$scope.personlistdto = $scope.searchFactory();
};
}
] );
This way the Factory VListLoader is called.