精华内容
下载资源
问答
  • 封装和信息隐藏

    千次阅读 2018-11-08 19:45:24
    文章目录3.1 信息隐藏原则3.1.1 封装与信息隐藏3.1.2 接口扮演的角色3.2 创建对象的基本模式3.2.1 门户大开型对象3.2.2 用命名规范区别私用成员3.2.3 作用域、嵌套函数和闭包3.2.4 用闭包实现私用成员3.3 更多高级...

    为对象创建私用成员是任何面向对象语言中最基本和有用的特性之一。通过将一个方法或属性声明为私用的,可以让对象的实现细节对其他对象保密以降低对象之间的耦合程度,可以保持数据的完整性并对其修改方式加以约束。在代码有许多人参与设计的情况下,这也可以使代码更可靠、更易于调试。简而言之,封装是面向对象的设计的基石。
    尽管JavaScript是一种面向对象的语言,它并不具备用以将成员声明为公用或私用的任何内置机制。目前有几种办法可以用来创建具有公用、私用和特权方法的对象,它们各有优缺点。

    3.1 信息隐藏原则

    3.1.1 封装与信息隐藏

    可以把封装和信息隐藏视为同一个概念的两种表述。信息隐藏是目的,封装是达到这个目的的技术。
    封装可以被定义为对对象的内部数据表现形式和实现细节进行隐藏。要想访问封装过的对象中的数据,只有使用已定义的操作这一种办法。通过封装可以强制实施信息隐藏。许多面向对象语言都使用关键字来说明某些方法和属性应被隐藏。但在JavaScript中没有这样的关键字,我们将使用闭包的概念来创建只允许从对象内部访问的方法和属性。这比使用关键字的办法更复杂。

    3.1.2 接口扮演的角色

    在向其他对象隐藏信息的过程中接口是如何发挥作用的呢?
    接口提供了一份记载着可供公众访问的方法的契约。它定义了两个对象间可以具有的关系。只要接口不变,这个关系的双方都是可替换的。大多数情况下,你将发现对可以使用的方法加以记载会很有好处。不是有了接口就万事大吉,你应该避免公开未定义于接口中的方法。否则其他对象可能会对那些并不属于接口的方法产生依赖,这是不安全的。因为这些方法随时都可能发生改变或被删除,从而导致整个系统失灵。
    一个理想的软件系统应该为所有类定义接口。这些类只向外界提供它们实现的接口中规定的方法,任何别的方法都留作自用。其所有属性都是私有的,外界只能通过接口中定义的存取操作与之打交道。但实际的系统很少能真正达到这样的境界。优质的代码应尽量向这个目标靠拢,但又不能过于刻板,把那些并不需要这些特性的简单项目复杂化。

    3.2 创建对象的基本模式

    JavaScript创建对象的基本模式有3种

    1. 门户大开型,这是最简单的一种,但它只能提供公用成员。
    2. 使用下划线表示私用方法或属性。
    3. 使用闭包来创建真正的私用成员,这些成员只能通过一些特权方法访问。

    以Book为例,该类满足这样的需求:存储关于一本书的数据,并实现一个以HTML形式显示这些数据的方法。
    你只负责创建这个Book类,别人会创建并使用其实例。它会被这样使用:

    // Book (isbn, title, author)
    var theHobbit = new Book('0-395-07122-4', 'The Hobbit', 'J. R. R. Tolkien');
    theHobbit.display();//通过创建HTML element显示数据
    

    3.2.1 门户大开型对象

    用一个函数来做其构造器,它的所有属性和方法都是公开的、可访问的。这些公用属性需要使用this关键字来创建。

    var Book = function(isbn, title, author) {
    	if(isbn == undefined) throw new Error('Book constructor requires an isbn.');
    	this.isbn = isbn;
    	this.title = title || 'No title specified';
    	this.author = author || 'No author specified';
    };
    Book.prototype.display = function () {
    	...
    }
    

    好像提供了ISBN就可以查到书籍了,可是这里有一个最大的问题,你无法检验ISBN数据的完整性,而不完整的ISBN数据有可能导致display方法失灵。如果Book对象在创建的时候没有什么问题,那么在display时也能正常工作才对,但是由于没有进行完整性检查,就不一定了。下面的版本强化了对ISBN的检查。

    var Book = function(isbn, title, author) {
    	if(!this.checkIsbn(isbn)) throw new Error('Book: Invalid ISBN.');
    	this.isbn = isbn;
    	this.title = title || 'No title specified';
    	this.author = author || 'No author specified';
    }
    Book.prototype = {
    	checkIsbn: function(isbn) {
    		if(isbn == undefined || typeof isbn != 'string'){
    			return false;
    		}
    		isbn = isbn.replace(/-/,'');
    		if(isbn.length != 10 && isbn.length !=13) {
    			return false;
    		}
    		var sum = 0;
    		if(isbn.length === 10) {//10位的ISBN
    			if(!isbn.match(/^\d{9}/)) {
    				return false;
    			}
    			for(var i = 0; i < 9; i++) {
    				sum += isbn.charAt(i) * (10-i);
    			}
    			var checksum = sum % 11;
    			if(checksum === 10) checksum = 'X';
    			if(isbn.charAt(9) != checksum) {
    				return false;
    			}
    		}
    		else {//13位的ISBN
    			if(!isbn.match(/^\d{12}/)) {
    				return false;
    			}
    			for(var i = 0; i < 12; i++) {
    				sum += isbn.charAt(i) * ((i % 2 === 0) ? 1 : 3);
    			}
    			var checksum = sum % 10;
    			if(isbn.charAt(12) != checksum) {
    				return false;
    			}		
    		}
    		return true;
    	},
    	display: function() {
    		...
    	}
    };
    

    checkIsbn保证ISBN是一个具有正确的位数和校验和的字符串。这样在创建对象的时候可以对ISBN的有效性进行检查,这可以确保display方法能正常工作。

    但问题又来了,即使在构造的时候能对ISBN进行检验,如果后续其他程序员把其他值赋给isbn,这时就检验不了了,

    theHobbit.isbn = '978-0261103283';
    theHobbit.display();
    

    为了保护内部数据,为每一个属性都提供了取值器和赋值器方法。

    • 取值器方法用于获取属性值,通常以getAttributeName这种形式命名;
    • 赋值器方法用于设置属性值,通常以setAttributeName这种形式命名。

    通过使用赋值器,你可以在把一个新值真正赋给属性之前进行各种检验。

    var Publication = new Interface('Publication', ['getIsbn', 'setIsbn', 'getTitle', 'setTitle', 'getAuthor', 'setAuthor', 'display']);
    
    var Book = function(isbn, title, author) {
    	this.setIsbn(isbn);
    	this.setTitle(title);
    	this.setAuthor(author);
    }
    
    Book.prototype = {
    	checkIsbn: function(isbn) {
    		...
    	},
    	getIsbn: function() {
    		return this.isbn;
    	},
    	setIsbn: function(isbn) {
    		if(!this.checkIsbn()) throw new Error('Book: Invalid ISBN.');
    		this.isbn = isbn;
    	},
    	getTitle: function() {
    		return this.title;
    	},
    	setTitle: function(title) {
    		this.title = title || 'No title specified.';
    	},
    	getAuthor: function() {
    		return this.author;
    	},
    	setAuthor: function(author) {
    		this.author = author || 'No author specified.';
    	},
    	display: function() {
    		...
    	}
    };
    

    这是使用门户大开型对象创建方式所能得到的最好结果。

    这里明确定义了接口、一些对数据具有保护作用的取值器和赋值器方法,以及一些有效性检验方法。

    这里还是有一个漏洞,虽然我们为设置属性提供了赋值器方法,但那些属性仍然是公开的,可以被直接设置的,而在这种方案中却无法阻止这种行为。

    不过这种方法易于使用,创建这样的对象不要求你深入理解作用域或调用链的概念。由于所有方法和属性都是公开的,派生子类和进行单元测试也很容易。唯一的弊端在于无法保护内部数据,而且取值器和赋值器也引入了额外的代码。

    3.2.2 用命名规范区别私用成员

    从本质上来说,这种模式与门户大开型对象创建模式如出一辙,只不过在一些方法和属性的名称前加了下划线以示其私用性而已。这种方法可以解决上一种方法带来的问题:无法阻止其他程序员无意中绕过的所有检验步骤。

    var Book = function(isbn, title, author) {
    	this.setIsbn(isbn);
    	this.setTitle(title);
    	this.setAuthor(author);
    }
    
    Book.prototype = {
    	checkIsbn: function(isbn) {
    		...
    	},
    	getIsbn: function() {
    		return this._isbn;
    	},
    	setIsbn: function(isbn) {
    		if(!this.checkIsbn()) throw new Error('Book: Invalid ISBN.');
    		this._isbn = isbn;
    	},
    	getTitle: function() {
    		return this._title;
    	},
    	setTitle: function(title) {
    		this._title = title || 'No title specified.';
    	},
    	getAuthor: function() {
    		return this._author;
    	},
    	setAuthor: function(author) {
    		this._author = author || 'No author specified.';
    	},
    	display: function() {
    		...
    	}
    };
    

    这种命名规范也可以应用于方法,例如checkIson方法应该是类私有的方法:

    	_checkIsbn: function(isbn) {
    		...
    	},
    

    下划线的这种用法是一个众所周知的命名规范,它表明一个属性或方法仅供对象内部使用,直接访问它或设置它可能会导致意想不到的后果。这有助于防止程序员对它的无意使用,却不能防止对它的有意使用。

    这并不是真正可以用来隐藏对象内部数据的解决方法,它主要适用于非敏感性的内部方法和属性。

    3.2.3 作用域、嵌套函数和闭包

    在讨论真正的私用性方法和属性的实现技术之前,我们先花点时间解释一下这种技术背后的原理。
    在JavaScript中,只有函数具有作用域。也就是说,在一个函数内部声明的变量在函数外部无法访问。私用属性就其本质而言就是希望在对象外部无法访问的变量,所以为实现这种拒访性而求助于作用域这个概念是合乎情理的。

    定义在一个函数中的变量在该函数的内嵌函数中是可以访问的:

    function foo() {
    	var a = 10;
    	function bar() {
    		a *= 2;
    	}
    	bar();
    	return a;
    }
    foo();//20
    

    一个简单的闭包例子:

    function foo() {
    	var a = 10;
    	function bar() {
    		a *= 2;
    		return a;
    	}
    	return bar;
    }
    var baz = foo();
    baz(); // 20
    baz(); // 40
    baz(); // 80
    

    可以看到,函数是在foo外部被调用,但它依然能够访问a,这是因为JavaScript中的作用域是词法性的。函数是运行在定义它们的作用域中,而不是运行在调用它们的作用域中。所以,bar被定义在foo的作用域中,就能访问foo中定义的变量,即使foo的执行已经结束。

    3.2.4 用闭包实现私用成员

    var Book = function (newIsbn, newTitle, newAuthor) {
    	// Private attributes.
    	var isbn, title, author;
    
    	// Private method.
    	function checkIsbn(isbn) {
    		...
    	}
    
    	// Privileged methods.
    	this.getIsbn = function () {
    		return isbn;
    	};
    	this.setIsbn = function (newIsbn) {
    		if(!checkIsbn(newIsbn)) throw new Error('Book: Invalid ISBN.');
    		isbn = newIsbn;
    	};
    
    	this.getTitle = function () {
    		return title;
    	};
    	this.setTitle = function (newTitle) {
    		title = newTitle || 'No title specified';
    	};
    
    	this.getAuthor = function () {
    		return author;
    	};
    	this.setAuthor = function (newAuthor) {
    		author = newAuthor || 'No author specified';
    	};
    
    	// Constructor code.
    	this.setIsbn(newIsbn);
    	this.setTitle(newTitle);
    	this.setAuthor(newAuthor);
    };
    
    // Public, non-privileged methods.
    Book.prototype = {
    	display: function() {
    		...
    	}
    }
    

    代码解读:

    • 使用var声明的变量或方法是私有的,因为没有用this关键字,这意味着它们只存在于Book构造器中
    • 要访问这些私有的变量和方法,需在Book中使用this关键字声明方法,这些方法被称为特权方法(privileged method),它们是公用的方法,因为声明在Book内部,所以在对象外部可以访问到私用属性和方法。
    • 任何不需要直接访问私用属性的方法都可以在Book.prototype中声明。
    • 每生成一个新的对象实例都将为每一个私用方法和特权方法生成一个新的副本。这会比其他做法更耗内存。
    • 不利于派生子类,因为所派生出的子类不能访问超类的任何私用属性或方法。相比之下,在大多数语言中,子类都能访问超类的所有私用属性和方法。故在JavaScript中用闭包实现私用成员导致的派生问题被称为“继承破坏封装”

    3.3 更多高级对象创建模式

    前面学习了创建对象的3种基本模式,下面再对一些高级一点的模式做一个简介。

    3.3.1 静态方法和属性

    静态成员是在类的层次上操作的,而不是在实例的层次上操作。每个静态成员都只有一份。
    下面是添加了静态属性和方法的Book类:

    var Book = (function() {
    	// Private static attributes.
    	var numOfBooks = 0;
    
    	// Private static method.
    	function checkIsbn(isbn) {
    		...
    	}
    
    	// Return the constructor.
    	return function (newIsbn, newTitle, newAuthor) {
    		// Private attributes.
    		var isbn, title, author;
    	
    		// Private method.
    		function checkIsbn(isbn) {
    			...
    		}
    	
    		// Privileged methods.
    		this.getIsbn = function () {
    			return isbn;
    		};
    		this.setIsbn = function (newIsbn) {
    			if(!checkIsbn(newIsbn)) throw new Error('Book: Invalid ISBN.');
    			isbn = newIsbn;
    		};
    	
    		this.getTitle = function () {
    			return title;
    		};
    		this.setTitle = function (newTitle) {
    			title = newTitle || 'No title specified';
    		};
    	
    		this.getAuthor = function () {
    			return author;
    		};
    		this.setAuthor = function (newAuthor) {
    			author = newAuthor || 'No author specified';
    		};
    	
    		// Constructor code.
    		numOfBooks++;
    		if(numOfBooks > 50) throw new Error('Book: Only 50 instances of Book can be created.');
    		this.setIsbn(newIsbn);
    		this.setTitle(newTitle);
    		this.setAuthor(newAuthor);	
    	}
    })();
    
    // 创建Public static method.
    Book.convertToTitleCase = function(inputString) {
    	...
    };
    
    // Public, non-privileged methods.
    Book.prototype = {
    	display: function() {
    		...
    	}
    }
    

    这里创建了一个闭包,将构造器从原来的普通函数变成了一个内嵌函数,并且作为返回值赋给变量Book。外层的函数只是用于创建一个可以用来存放静态私用成员的闭包,这些静态私用成员不会为Book的每一个实例都创建一个新的副本。
    如何判断一个私用方法是否应该被设计为静态方法?
    看它是否需要访问任何实例数据。如果它不需要,则设计为静态方法会更有效率,因为它只会被创建一份。

    3.3.2 常量

    常量是一些不能被修改的变量。在JavaScript中,可以通过创建只有取值器而没有赋值器的私有变量来模仿常量。

    var Class = (function() {
    	// Constants (created as private static attributes.).
    	var UPPER_BOUND	= 100;
    	// Constructor.
    	var ctor = function (constructorArgument) {
    		...
    	};
    	// Privileged static method.
    	ctor.getUPPER_BOUND = function() {
    		return UPPER_BOUND;
    	};
    	...
    	// Return the constructor
    	return ctor;
    })();
    

    如果需要使用许多常量,但你不想为每个常量都创建一个取值器方法,那么可以创建一个通用的取值器方法,如下:

    var Class = (function() {
    	// Constants (created as private static attributes.).
    	var constants ={
    		UPPER_BOUND: 100,
    		LOWER_BOUND: -100
    	};
    	// Constructor.
    	var ctor = function (constructorArgument) {
    		...
    	};
    	// Privileged static method.
    	ctor.getConstant = function(name) {
    		return constants[name];
    	};
    	...
    	// Return the constructor
    	return ctor;
    })();
    Class.getConstant('UPPER_BOUND');
    

    3.3.3 单体和对象工厂

    单体模式和工厂模式也使用闭包来创建受保护的变量空间,后面部分会详细讨论这两种模式。在此简单介绍一下:

    • 单体模式使用一个由外层函数返回的对象字面量来公开特权成员,而私用成员则被保护性地封装在外层函数的作用域中。它使用的技术是:外层函数在定义之后立即执行,其结果被赋给一个变量。本章的例子中外层函数返回的都是一个函数,而单体模式返回的则是一个对象字面量。
    • 对象工厂也可以使用闭包来创建具有私用成员的对象。其最简形式就是一个类构造。

    3.4 封装之利

    要是在创建对象时不用操心闭包和特权方法,事情就会简单得多。那么,不厌其烦的隐藏实现细节究竟有什么好处?
    封装保护了内部数据的完整性。通过将数据的访问途径设置为取值器和赋值器这两个方法,可以获得对取值和赋值的完全控制。这可以减少其他函数所需的错误检查代码的数量,并确保数据不会处于无效状态。
    封装提高了对象的可重用性,使其在必要的时候可以被替换。使用私用变量也有助于避免命名空间冲突。
    封装还使你可以大幅改动对象的内部细节,而不会影响到其他部分的代码。总的来说,代码的修改变得更轻松,如果对象的内部数据都是公开的话,你不可能完全清楚代码的修改会带来什么结果。

    3.5 封装之弊

    私用方法很难进行单元测试。因为他们及其内部变量都是私用的,在对象外部无法访问到它们。要么通过使用公用方法来提供访问途径(这样一来就葬送了使用私用方法所带来的大多数好处),要么设法在对象内部定义并执行所有测试单元。最好的解决办法是只对公用方法进行单元测试。这是一种广为接受的处理方式。
    使用封装意味着不得不与复杂的作用域链打交道,而这会使错误调试变得更加困难。有时候会很难区分来自不同作用域的大批同名变量。这个问题不是经过封装的对象所特有的,但实现私用方法和属性所需的闭包会让它变得更复杂。
    过度封装也是一个潜在的问题。
    最大的问题在于JavaScript中实现封装的困难。JavaScript本来就是一门与多数面向对象语言大相径庭的语言,而封装技术设计的调用链和定义后立即执行的匿名函数等概念更是加大了学习难度。此外,封装技术的应用还使不熟悉特定模式的人难以理解既有代码。注释和程序文档可以提供一些帮助,但并不能完全解决这个问题。

    3.6 小结

    本章讨论了信息隐藏的概念以及如何用封装这种手段来实现它。因为JavaScript没有对封装提供内置的支持,所以其实现必须依赖于一些其他技术。本书后面的多数章节都依赖于这些基本技术,因此你得好好品味一下本节的内容。只要理解了JavaScript中作用域的特点,你就能模仿出各种面向对象的技术。

    展开全文
  • 在整个介绍信息隐秘技术部分, 为了统一起见, 我们约定以下名词: 称需要隐秘的信息为秘密信息( secret) , 秘密信息隐藏的媒介叫做载体( cover) , 隐藏后的结果叫做隐蔽载体( stego-cover) 一、图...

    从本章开始, 我们将具体接触到许多数字信息的隐写术。为了与后面数字水印技术相区别, 我们也将隐写术称为信息隐秘技术。本章主要阐述图像信息作为秘密信息的隐藏, 即图像降级隐写。
    在整个介绍信息隐秘技术部分, 为了统一起见, 我们约定以下名词: 称需要隐秘的信息为秘密信息( secret) , 秘密信息隐藏的媒介叫做载体( cover) , 隐藏后的结果叫做隐蔽载体( stego-cover)
    一、图像降级
    主体对客体的读写一般应满足以下两个规则:
    规则 1: 主体只能向下读, 不能向上读。
    规则 2: 主体只能向上写, 不能向下写。
    我们通常所说的信息降级, 就是通过将秘密信息嵌入较低安全级别的客体中, 破坏了第二个规则, 从而使机密的信息看上去不再机密。在伪装技术中我们经常要这样做, 以使秘密信息被伪装成为低级别的信息, 不易被发现。图像降级就是伪装技术的一个应用。
    二、简单的图像信息伪装技术
    1.直接 4bit 替换法
    这是将秘密图像信息嵌入载体图像的一种最简单的方法,指直接用秘密图像像素值的高 4bit 去替换载体图像像素值的低 4bit。

    % 文件名: imagehide. m
    % 函数功能: 直接将秘密图像的高 4bit 隐藏在 RGB 载体图像的 R, G, B 层中所
    选的那一层的低 4bit, 并将秘密图像提取出来, 最后显示。要求载体图像的大小大于
    等于秘密图像的大小, 且秘密图像是二值或灰度图像
    % 输入格式:
    % data = imagehide( ′c: \ lenna. bmp′, ′c: \ woman. bmp′, ′c: \mix. bmp′, ′bmp′, 3 )
    % 参数说明
    % cover 是载体图像的地址
    % message 是秘密图像的地址
    % goleimage 是隐藏后图像的地址
    % permission 是图像的类型
    % level 是作为载体的具体层, R 为 1 , G 为 2, B 为 3
    % data 是隐藏后图像的矩阵
    
    function data = imagehide( cover, message, goleimage, permission, level)
    % 提取图像信息并分层
    cover = imread( cover, permission) ;
    data = cover;
    msg = imread( message, permission) ;
    [ row, col] = size( cover) ;
    cover1 = cover(∶,∶, level) ;
    % 置载体图像 R 层的低 4bit 为 0
    for i = 1∶row
    		for j = 1∶col /3
    				cover1( i, j) = bitand( cover1( i, j) , 240) ;
    		end
    end
    % 置秘密图像的低 4bit 为 0
    takemsg4 = bitand( msg, 240) ;
    % 将秘密图像的高 4bit 右移 4 位
    shiftmsg4 = bitshift( takemsg4, - 4) ;
    % 图像隐藏
    for i = 1∶row
    		for j = 1∶col /3
    				cover1( i, j) = bitor( cover1( i, j) , shiftmsg4( i, j) ) ;
    		end
    end
    % 写回并保存
    data(∶,∶, level) = cover1;
    imwrite( data, goleimage, permission) ;
    % 提取秘密图像信息, 检测隐藏效果
    data = imread( goleimage, permission) ;
    [ row, col] = size( data) ;
    A = data(∶,∶, level) ;
    for i = 1∶row
           for j = 1∶col /3
    				A( i, j) = bitand( A( i, j) , 15) ;
           end
    end
    A = bitshift( A, 4) ;
    % 显示结果
    subplot( 221) , imshow( cover) ; title( ′载体图像′) ;
    subplot( 222) , imshow( message) ; title( ′秘密图像′) ;
    subplot( 223) , imshow( data) ; title( ′隐藏后的图像′) ;
    subplot( 224) , imshow( A) ; title( ′提取的秘密图像′) ;
    

    但无论选择R G B三层中的哪层嵌入,都会在不同程度上对原始图像造成破坏
    考虑到第一章中我们阐述的 RGB 颜色模型, 将秘密图像隐藏在一层中, 容易导致该点的色彩向相应的坐标上发生绝对偏移, 从而使得该像素点的色彩的相应分量突出。所以, 我们不能笼统地认为图像隐藏在某层比较好而隐藏在某层不好, 这是因为对于具体的某个像素点其哪个颜色分量突出是不确定的。但是, 我们可以通过改进算法来限制这种颜色沿相应坐标的绝对偏移。

    例如, 可将秘密图像像素值的高 4bit 分别藏于载体图像 R, G, B 层像素值的最低位或次低位, 即将秘密图像的高 2bit 藏于 R 层, 另外 2bit 分别藏于 G 层和 B 层, 此时像素色彩的改变就不是沿一个坐标方向而改变, 而是在整个 RGB 空间中发生偏移, 改变后的颜色坐标点与改变前的颜色坐标点的距离( 数学上的范数) 比单纯在一个分量上改变的两点距离要小, 这样对载体图像的影响会更小。在实际应用中, 还应该考虑隐藏的鲁棒性等问题。

    2.对第 4bit 的考察
    可以发现,直接替换 4 bit 后, 图像还是有一些变化的, 也就是说, 替换容量大使图像的保真度降低( 可通过实验看到替换 3bit 的效果比替换 4bit 的效果要好)
    在这种情况下,我们可以用秘密信息图像像素值的高3bit去替换载体图像像素值的低3bit,至于第 4bit 则要具体分析
    其假设前提是: 如果只对图像进行 3bit 替换, 是不会对图像的视觉效果造成影响的。事实上, 这种假设是可以成立的

    首先, 我们引入一个相似度的概念, 所谓相似度, 是指两图像块中同一坐标下的像素中第 4bit 相同的像素数量占一块图像全部像素的比例, 表示为:μ=s/64
    其中 s 为第 4bit 相同的像素数量 64 为 8× 8 块中的总像素数
    根据 μ的取值我们来确定该块各像素第 4bit 的隐藏策略。
    我们先计算相应块的载体图像与秘密图像在第 4bit 的相似度 μ, 如果 μ大于某一阈值 T, 则可直接用秘密图像的第 4 bit 替换载体图像的第 4bit, 如果 μ小于阈值1 - T, 则先将秘密图像的第 4bit 取反后再替换, 若 μ介于 1 - T 和 T 之间, 则不进行替换。当然, 要用一个替换表对第 4bit 进行替换或取反替换了的块进行记录, 并且将此表也嵌入到载体图像中。编写函数 fourthbitcmp. m 完成记录替换表的实验, 函数代码如下:

    % 文件名: fourthbitcmp. m
    % 函数功能: 计算秘密图像和选择的载体图像层, 对于第 4bit 的每一个 8× 8 块,哪些可以用秘密图像去替换载体图像, 并返回一个替换表 count, 要求两个图像都可以整数 8× 8 分块
    % 输入格式: count = fourthbitcmp( ′c: \lenna. bmp′, ′c: \woman. bmp′, ′bmp′, 3, 0. 7)
    % 参数说明:
    % cover 是载体图像的地址
    % message 是秘密图像的地址
    % permission 是图像的类型
    % level 是作为载体的具体层。R 为 1, G 为 2 , B 为 3
    % count 是替换表
    % threshold 是阈值
    function count = fourthbitcmp( cover, message, permission, level, threshold)
    % 提取图像信息并分层
    cover = imread( cover, permission) ;
    data = cover;
    msg = imread( message, permission) ;
    cover1 = cover(∶,∶, level) ;
    % 对 cover 和 msg 的第 4bit 进行处理
    tempc = cover1;
    tempm = msg;
    tempc = bitand( tempc, 8) ;
    tempm = bitand( tempm, 8) ;
    temp = bitxor( tempm, tempc) ;
    [ row, col] = size( temp) ;
    % 记录图像每个分块的 n 值
    k1 = 0;
    k2 = 0;
    a = row* col /64;
    count = zeros( [ 1 a] ) ;
    for i = 1∶a
    	for m = 1∶8
    		for n = 1∶8
    				if temp( 8* k1 + m, 8* k2 + n) == 0
    					count( 1, i) = count( 1, i) + 1;
    				end
    		end
    	end
    	k2 = k2 + 1;
    	if k2* 8 == col
    			k2 = 0;
    					k1 = k1 + 1;
    			end
    	end
    % 计算每块的 μ值并与阈值进行比较
    count = count /64;
    for i = 1∶a
    	if count( i) >= threshold
    		count( i) = 1; % 可以替换
    			elseif count( i) < 1 - threshold
    				count( i) = - 1; % 取反
    			else
    		        count( i) = 0; % 不能处理
    	end
    end
    

    依据本算法, 在同一阈值下经不同层计算出的替换表中 0 的个数, 个数越少的层越适宜当做载体。当然, 为了简单起见, 也可以不加分块直接计算秘密图像与载体图像 R、G、B 层中哪一层的相似度高, 就选择哪一层为载体。
    三、图像置乱
    置乱实际上就是图像的加密, 与加密保证安全性不同的是, 将置乱的图像作为秘密信息再进行隐藏, 可以很大限度地提高隐蔽载体的鲁棒性, 所以图像置乱是信息隐藏中常用的一项技术。
    1、变化模板形状的图像置乱算法
    变化模板形状的图像置乱算法的思想如下:
    ① 对原图像取一个固定模板, 模板中像素位置排列如图 4. 10 所示。
    ② 做一个与原图像模板不同的置乱模板, 如图 4. 11 所示, 在置乱模板中把图像模板中的像素位置按一定次序填入
    ③ 将置乱模板中的像素位置再按一定的次序填回到原图像模板中就得到了置乱后的图像模板( 图 4. 12 的模板是按从左到右、从上到下的次序依次读取置乱模板中像素位置) 。
    在这里插入图片描述
    可以发现, 这种置乱算法是对合的
    与前面 Zigzag 变换一样, 我们也采取查表的方法编写程序。由于我们固定了置乱模板的大小, 所以在对图像置乱前我们要对其进行边界修补。如取置乱模板为 32× 32, 则要求秘密图像的尺寸为 32× 32,64× 64 , 128× 128, …。假设一幅图像的尺寸为 32× 31 , 则应该对其增加 1 列数据。
    变换表分为行表和列表, 同一坐标下的行列表中的数据结合起来所指示的像素将被置乱到这一坐标下。
    此外, 在图像置乱机制中引入一个简单的密钥控制。将由密钥生成的第一个[ 128, 255] 的随机整数与置乱的结果进行模 2 加。编写程序 diamondreplace. m 完成置乱实验。其中需要调用查表程序 replace32 fun. m, 函数代码如下:
    ( 1 ) 主函数: diamondreplace. m

    % 文件名: diamondreplace. m
    % 函数功能: 本函数将完成对输入的图像信号按菱形置换策略进行置乱
    % 输入格式举例: result = diamondreplace( secretimage, 1983 )
    % 参数说明:
    % matrix 为输入图像矩阵
    % key 为控制密钥
    % result 为置乱后的结果
    function result = diamondreplace( matrix, key)
    % 分析原图像尺寸并补遗
    [ m, n] = size( matrix) ;
    rowadd = 32-mod( m, 32) ;
    coladd = 32-mod( n, 32 ) ;
    if rowadd== 32
    rowadd = 0;
    end
    if coladd== 32
    coladd = 0;
    end
    input = uint8( zeros( [ m + rowadd n + coladd] ) ) ;
    input( 1∶m, 1∶n) = matrix;
    % 密钥生成随机数
    rand( ′seed′, key) ;
    control = randint( 1, 1 , [ 128 255] ) ;
    % 查表置乱
    fun = @replace32fun; % 调用子函数
    result = blkproc( input, [ 32 32] , fun) ;
    result = bitxor( result, control( 1 , 1) ) ;
    

    ( 2 ) 查表函数: replace32fun. m

    function result = replace32fun( matrix)
    % 行转换表
    row = [ 16 15 17 14 16 18 …] % 此处略去, 具体内容请见表 4. 3
    col = [ 17 18 17 20 18 16 …] % 此处略去, 具体内容请见表 4 . 4
    for i = 1∶32
    for j = 1∶32
    result( i, j) = matrix( row( i, j) , col( i, j) ) ;
    end
    end
    

    woman图像置乱后的效果
    将图像的原始信息破坏得越大越好, 不过, 这种破坏一定要是可以复原的

    2.图像的幻方变换

    % 文件名: magicsquares. m
    % 函数功能: 本函数将完成 n 阶二维幻方的求取 . 要求 n 为奇数
    % 输入格式举例: result = magicsquares( 5)
    % 参数说明:
    % n 为阶数
    % result 为求得的二维幻方
    function result = magicsquares( n)
    if mod( n, 2) == 0
    error( ′n 要求为奇数′) ;
    end
    result = zeros( n) ;
    j = floor( n /2 ) + 1; % 中间 1 列
    i = n + 1; % 便于以后从第 n 行开始考虑起
    result( 1, j) = 1 ;
    for k = 2∶n* n % 依次考虑后 n^2 - 1 个数
    i = i - 1 ;
    j = j + 1 ; % 行数减 1, 列数加 1
    if i < 1 && j > n % 特殊情况 4
    i = i + 2 ;
    j = j - 1 ;
    else
    if i < 1 % 特殊情况 1
    i = n;
    end
    if j > n % 特殊情况 2
    j = 1;
    end;
    end;
    if result( i, j) == 0
    result( i, j) = k;
    else % 特殊情况 3
    i = i + 2 ;
    j = j - 1 ;
    result( i, j) = k;
    end
    end
    
    

    我们知道, 要图像置乱是为了增加隐藏的鲁棒性。一个置乱的图像无论是合法用户还是非法用户都看不懂, 要使合法用户能完整地读取秘密信息, 就要满足两个条件:
    ①仅有合法用户知道的密钥参与运算。
    ②置乱算法本身可以保证图像复原, 即算法是可逆的。
    幻方置乱的思想其实也是查表思想,其运算具有准对合性,具体算法实现后面再阐述
    编 写 函 数 magicreplace. m 完 成 置 乱 实 验, 其 中 需 要 调 用 查 表 函 数replacemagicfun. m。前主函数存放 11 阶标准幻方, 子函数存放表 4. 6 , 函数代码如下:
    ( 1 ) 幻方置乱主函数: magicreplace.m

    % 文件名: magicreplace. m
    % 函数功能: 本函数将完成对输入的图像信号按幻方置换策略进行置乱
    % 输入格式举例: result = magicreplace( secretimage, 1, 1983)
    % 参数说明:
    % matrix 为输入图像矩阵
    % key 为控制密钥
    % eord 为 1 表示置乱变换, 为 0 表示复原变换
    % result 为置乱后的结果
    function result = magicreplace( matrix, eord, key)
    % 分析原图像尺寸并补遗
    [ m, n] = size( matrix) ;
    rowadd = 11-mod( m, 11) ;
    coladd = 11-mod( n, 11 ) ;
    if rowadd == 11
    rowadd = 0;
    end
    if coladd == 11
    coladd = 0;
    end
    input = uint8( zeros( [ m + rowadd n + coladd] ) ) ;
    input( 1∶m, 1∶n) = matrix;
    % 密钥生成随机数
    rand( ′seed′, key) ;
    control = randint( 1, 1 , [ 1 121] ) ;
    % 11 阶标准幻方
    magic =
    [ 38 52 66 69 83 97 100 114 7 21 24 
      61 75 78 92 106 120 2 16 30 44 47
      84 98 101 115 8 22 25 39 53 56 70 
      107 121 3 17 31 34 48 62 76 79 93 
      9 12 26 40 54 57 71 85 99 102 116
      32 35 49 63 77 80 94 108 111 4 18 
      55 58 72 86 89 103 117 10 13 27 41
      67 81 95 109 112 5 19 33 36 50 64
      90 104 118 11 14 28 42 45 59 73 87
      113 6 20 23 37 51 65 68 82 96 110 
      15 29 43 46 60 74 88 91 105 119 1 ] ; 
    if eord == 0
    control = 121 -control;
    elseif eord == 1
    control = control;
    else
    error( ′输入参数错误′) ;
    end
    % 幻方变换主过程
    for define = 1∶key% control
    	for r = 1∶11
    		for c = 1∶11
    			magic( r, c) = magic( r, c) -1;
    			if magic( r, c) == 0
    					magic( r, c) = 121;
    			end
    		end
    	end
    end
    % 查表置乱
    fun = @replacemagicfun; % 调用子函数
    result = blkproc( input, [ 11 11] , fun, magic) ;
    

    ( 2 ) 行列转换表子函数: replacemagicfun. m

    % 11 阶幻方的行列查找表程序
    function result = replacemagicfun( matrix, P1 )
    % 初始化 11 阶幻方的行列查找表
    row = [ 11 , 2, 4, 6, 8, 10, 1, 3, 5, 7, 9, 5, 7, 9, 11, 2, 4, 6 , 8, 10, 1 , 3, 10, 1 , 3, 5, 7, 9,
    11, 2, 4, 6 , 8, 4, 6, 8, 10, 1, 3, 5, 7, 9 , 11, 2 , 9 , 11, 2, 4, 6, 8 , 10, 1, 3, 5 , 7, 3, 5, 7 , 9, 11 , 2,
    4 , 6 , 8, 10 , 1, 8, 10 , 1, 3, 5, 7, 9, 11, 2, 4, 6 , 2 , 4 , 6, 8, 10, 1 , 3, 5, 7, 9, 11, 7, 9, 11, 2, 4 , 6,
    8 , 10, 1, 3 , 5, 1, 3, 5, 7, 9, 11, 2, 4, 6 , 8, 10 , 6 , 8, 10 , 1, 3, 5, 7, 9, 11, 3, 4] ;
    col = [ 11, 7, 3, 10, 6, 2, 9, 5, 1, 8, 4 , 2, 9, 5, 1, 8, 4, 11, 7, 3 , 10, 6, 4, 11, 7 , 3, 10 , 6,
    2 , 9 , 5, 1, 8, 6, 2, 9, 5 , 1, 8, 4, 11, 7, 3, 10 , 8, 4, 11, 7 , 3, 10, 6, 2, 9, 5 , 1, 10, 6, 2 , 9, 5, 1,
    8 , 4 , 11, 7 , 3, 1, 8, 4, 11, 7, 3, 10, 6, 2, 9, 5 , 3 , 10, 6, 2, 9, 5 , 1, 8, 4, 11 , 7, 5, 1, 8 , 4, 11 , 7,
    3 , 10, 6, 2 , 9, 7, 3, 10, 6, 2, 9, 5, 1, 8 , 4, 11 , 9 , 5, 1, 8, 4, 11, 7, 3, 10, 6, 2] ;
    for i = 1: 11
    	for j = 1: 11
    		result( i, j) = matrix( row( P1 ( i, j) ) , col( P1( i, j) ) ) ;
    	end
    end
    

    3.图像的 Ha sh 置乱
    前面的两种置乱都是对图像分块进行的, 而且其共同的问题是密钥控制并不得力。下面介绍的一种图像置乱方法实际上就是我们在 2. 6. 3 节中介绍的 Hash 置换的特例———对于 m× n 个像素点, 我们要求随机置换 m× n 个, 就完成了图像的 Hash置乱。鉴于该算法具有无冲突( collision) 和强密钥控制的特点, 显然是一个很好的图像置乱算法。需要说明的是, 这种算法不是对合的, 所以在实现上较前两种复杂一些。另外, 其算法执行起来也比较费时间。编写函数 hashdisturb. m 完成实验

    % 文件名: hashdisturb. m
    % 函数功能: 本函数将完成对输入的图像信号按 Hash 置换策略进行置乱
    % 输入格式举例: result = hashdisturb( secretimage, 1, 1983 , 421, 1121)
    % 参数说明:
    % matrix 为输入图像矩阵
    % key1 -key3 为控制密钥
    % eord 为 1 表示置乱变换, 为 0 表示复原变换
    % result 为置乱后的结果
    function result = hashdisturb( matrix, eord, key1, key2, key3 )
    % 分析原图像尺寸并补遗
    [ m, n] = size( matrix) ;
    % 调用随机置换函数
    [ row, col] = hashreplacement( matrix, m* n, key1, key2, key3) ;
    % 置乱函数
    count = 1;
    if eord == 1
    	for i = 1∶m
    		for j = 1∶n
    			result( i, j) = matrix( row( count) , col( count) ) ;
    			count = count + 1;
    		end
    	end
    end
    % 复原函数
    if eord == 0
    	for i = 1∶m
    		for j = 1∶n
    			result( row( count) , col( count) ) = matrix( i, j) ;
    			count = count + 1;
    		end
    	end
    end
    
    

    4.隐藏置乱图像的优点
    置乱图像隐藏的抗恶意攻击性能
    经过多次置乱后, 图像就会彻底地改变, 从置乱后的图像上根本看不到原图像的任何特征。使用置乱方法为什么可以增加图像伪装的鲁棒性呢?
    首先, 将图像置乱后, 将得到一幅杂乱无章的图像, 这个图像无色彩、无纹理、无形状, 从中无法读取任何信息, 那么, 将这样一幅图嵌入到另一幅普通图像时就不易引起那幅图色彩、纹理、形状的太大改变, 甚至不会发生改变, 这样人眼就不易识别,从而逃出了第三方的视线。

    其次, 由于秘密图像是置乱后的图像, 根据上述图像的“三无”特征, 第三方根本不可能对其进行色彩、纹理、形状等的统计分析, 即便他们截取到了秘密图像, 也是无能为力的。如果第三者企图对秘密图像进行反置乱, 这也是不可能的, 由于图像置乱有很多种方法, 每种方法又可以使用不同的置乱模板算法, 设置不同的参数, 使用者有很大的自由度, 他可以根据自己的想法得到不同的结果, 相反, 这给企图截获秘密信息的第三方带来了很大的困难, 使他们需要耗费巨大的计算量来穷举测试各种可能性

    最后, 我们再设想一下, 如果第三方反置乱不成, 在隐蔽载体上恶意修改怎么办?通过实验我们知道, 用置乱的方法是可以抵抗这些攻击的, 因为对秘密图像进行反置换的过程, 就使得第三方在图像上所涂、画的信息分散到画面的各个地方, 形成了点状的随机噪声, 对视觉影响的程度不大。图 4. 20 是我们随意对隐蔽载体进行 3 种恶意攻击后提取的秘密图像内容。可以看到, 即使是在攻击 3 下, 秘密图像的轮廓依然可见, 这是在未置乱图像的隐藏下不可想像的。当然, 为了使提取的信息更为清晰,最好对破坏严重的图像进行边界保持的中值滤波等方面的处理, 以去除随机噪声。

    展开全文
  • mysql sql 隐藏信息

    千次阅读 2019-09-03 15:53:37
    需求天天有,每天不一样,今天主要介绍一下,只用mysql的内置函数实现信息隐藏 简单列一下常用函数: 传送门: https://www.cnblogs.com/geaozhang/p/6739303.html 看看常用函数的用法 接下来讲解一下...

    需求天天有,每天不一样,今天主要介绍一下,只用mysql的内置函数实现信息的隐藏

     

    简单列一下常用函数:

    传送门:

    https://www.cnblogs.com/geaozhang/p/6739303.html

    看看常用函数的用法

     

    接下来讲解一下怎么个思路

     

    首先,隐藏部分信息

    姓名,只显示姓,如 张*,李*,王***

    首先,应该想到求长度,补齐这俩函数

    求长度:CHAR_LENGTH(U.real_name)

    截取:substring(U.real_name,1,1)

    补齐:RPAD(substring(U.real_name,1,1),CHAR_LENGTH(U.real_name),'*')

     

    还有一个经常用的函数 CONCAT(str1,str2)

    就这么几个,灵活应用,看结果吧

     

    结果:

    
    SELECT
            U.id,
            RPAD(substring(U.real_name,1,1),CHAR_LENGTH(U.real_name),'*') realName,
            CONCAT(substring(U.telephone,1,3),'****',substring(U.telephone,8,11)) telephone,
            CONCAT(
                RPAD(substring(substring_index(U.email, '@', 1), 1, 3),CHAR_LENGTH(substring_index(U.email, '@', 1)),'*'),
                '@',
                substring_index(U.email, '@', -1)
            ) email
    FROM
            USER U
    WHERE
            U.flag = 0

     

    展开全文
  • Matlab-LSB信息隐藏实验

    万次阅读 多人点赞 2018-07-05 11:16:26
    一、实验内容实验完成形式: 用MATLAB函数实现LSB信息隐藏和提取实验选择载体: 512×512灰度图像实验效果和分析: 1.完成基本的LSB信息隐藏及提取2.能随机选择嵌入位进行信息隐藏及提取(考虑安全性因素) 3....

    一、实验内容

    实验完成形式: 
    用MATLAB函数实现LSB信息隐藏和提取
    实验选择载体: 
    512×512灰度图像
    实验效果和分析: 
    1.完成基本的LSB信息隐藏及提取
    2.能随机选择嵌入位进行信息隐藏及提取(考虑安全性因素) 
    3.能够计算PSNR,分析信息隐藏图像质量
    4.完成对秘密信息的图像载体进行攻击,采用的攻击方法: jpeg压缩,resize缩放                         

    5.计算每种攻击方法提取的秘密信息误码率 

    二、实验涉及到的相关算法

    1.基本LSB信息隐藏及提取算法——图像的第一层是LSB层,替换后对原图像的影响较小,第8层为MSB层对原图像影响较大。 
    1)读入图像载体:gray=imread('lena_gray.bmp');
    2)读入要隐藏的图像,并转换为二进制:woman=imread('woman_rgb.bmp'); woman_to_binary=im2bw(woman);
    3)在图像载体的第一层隐藏图像:gray_set=bitset(gray,1,woman_to_binary);
    4)提取隐藏的图像:gray_get_1=bitget(gray_set,1);
    算法实现源代码:
    gray=imread('lena_gray.bmp');
    gray_8=bitget(gray,8);
    gray_6=bitget(gray,6);
    gray_7=bitget(gray,7);
    woman=imread('woman_rgb.bmp');
    woman_to_binary=im2bw(woman);
    gray_set=bitset(gray,1,woman_to_binary);
    gray_set_8=bitset(gray,8,woman_to_binary);
    gray_get_8=bitget(gray_set_8,8);
    gray_get_1=bitget(gray_set,1);
    subplot(221),imshow(gray),title('原始图像');
    subplot(222),imshow(logical(gray_8)),title('原始图像的第8层');
    subplot(223),imshow(gray_set_8),title('在第8层隐藏信息后');
    subplot(224),imshow(logical(gray_get_8)),title('获取隐藏的图像');
    figure,%新打开一个窗口
    subplot(221),imshow(gray),title('原始图像');
    subplot(222),imshow(woman_to_binary),title('要隐藏的图像');
    subplot(223),imshow(gray_set),title('在第1层隐藏信息后');
    subplot(224),imshow(logical(gray_get_1)),title('获取隐藏的图像');

    2.完成随机选择嵌入位进行LSB信息隐藏及提取算法。


    随机选择嵌入位,嵌入水印信息,input为载体图像,file为要嵌入的文本文件,output为嵌入水印后的图像,key为随机数种子。

    %2.随机选择嵌入位
    function [ste_cover,len_total]=rand_lsb_hide(input,file,output,key)
    %读入图像矩阵
    cover=imread(input);
    ste_cover=cover;
    ste_cover=double(ste_cover); 
    %将文本文件转换为二进制
    f_id=fopen(file,'r');
    [msg,len_total]=fread(f_id,'ubit1');
    %判断嵌入的信息量是否过大
    [m,n]=size(ste_cover);
    if len_total>m*n
      error('嵌入信息量过大,请重新选择图像');
    end
    %p作为消息嵌入位计数器
    p=1;
    %调用随机间隔函数选取像素点
    [row,col]=randinterval(ste_cover,len_total,key);
    %在LSB隐藏信息
    for i=1:len_total
        ste_cover(row(i),col(i))=ste_cover(row(i),col(i))-mod(ste_cover(row(i),col(i)),2)+msg(p,1);
        if p==len_total
            break;
        end
        p=p+1;
    end
    ste_cover=uint8(ste_cover);
    imwrite(ste_cover,output);
    %显示实验结果
    subplot(1,2,1);imshow(cover);title('原始图像');
    subplot(1,2,2);imshow(output);title('隐藏信息的图像');

    实现效果:


    读取嵌入的水印信息,output为嵌入水印后的图像,goalfile为提取出的水印文件,key与嵌入水印时的值相同:

    function result = rand_lsb_get(output,len_total,goalfile,key)
    ste_cover=imread(output);
    ste_cover=double(ste_cover);
    %判断嵌入信息量是否过大
    [m,n]=size(ste_cover);
    if len_total>m*n
      error('嵌入信息量过大,请重新选择图像');
    end
    frr=fopen(goalfile,'a');
    %p作为消息嵌入位计数器,将消息序列写回文本文件
    p=1;
    %调用随机间隔函数选取像素点
    [row,col]=randinterval(ste_cover,len_total,key);
    for i=1 :len_total
        if bitand(ste_cover(row(i),col(i)),1)==1
            fwrite(frr,1,'ubit1');
            result(p,1)=1;
        else
            fwrite(frr,0,'ubit1');
            result(p,1)=0;
        end
        if p ==len_total
            break;
        end
        p=p+1;
    end
    fclose(frr);

    随机数生成算法:

    %书上50页
    function [row,col]=randinterval(matrix,count,key)
    %计算间隔的位数
    [m,n]=size(matrix);
    interval1=floor(m*n/count)+1;
    interval2=interval1-2;
    if interval2==0
        error('载体太小,不能将私密信息隐藏进去');
    end
    %生成随机序列
    rand('seed',key);
    a=rand(1,count);
    %初始化
    row=zeros([1 count]);
    col=zeros([1 count]);
    %计算row,col
    r=1;
    c=1;
    row(1,1)=r;
    col(1,1)=c;
    for i=2:count
        if a(i)>=0.5
            c=c+interval1;
        else
            c=c+interval2;
        end
        if c>n
            r=r+1;
            if r>m
                error('载体太小,不能私密信息隐藏进去');
            end
            c=mod(c,n);
            if c==0
                c=1;
            end
        end
        row(1,i)=r;
        col(1,i)=c;
    end

    3.计算误码率的算法——分别对含有秘密信息的图像载体进行攻击,攻击方式为jpeg压缩,resize缩放,根据不同的压缩比例,缩放比例的分别计算误码率并显示如下:

    这部分代码是参考别人的博客编写的:https://blog.csdn.net/cheeseandcake/article/details/52997903?locationNum=11&fps=1

    function ber_resize=calcute_resize_ber(input,messagefile,len_total,key)
    for resize =0.5:1:10
    %读取已经隐藏信息的图像。
    fp=imread(input);
    %使用 imresize 函数对图像进行缩放,设定缩放比例。
    output=imresize(fp,resize,'bicubic'); %利用双三次插值方法将 Ifp放大 size 倍
    intchanged=double(output);
    %p作为消息嵌入位计数器,将消息序列写回文本文件
    p=1;
    %调用随机间隔函数选取像素点
    [row,col]=randinterval(intchanged,len_total,key);
    for i=1 :len_total
        if bitand(intchanged(row(i),col(i)),1)==1
            result(p,1)=1;
        else
            result(p,1)=0;
        end
        if p ==len_total
            break;
        end
        p=p+1;
    end
    %读取原文件,即隐藏的信息,以二进制读取。并取得消息长度
    message=fopen(messagefile,'r'); 
    %按位以二进制形式读取文本内容与长度
    [msg,len_total]=fread(message,'ubit1');
    %比较取得的信息和原信息的每一位,记录不相等位数的个数。
    bit_error=find(result~=msg); %寻找不相等的位置 
    bit_error_count=size(bit_error,1); %统计不相等的个数
    %用不相等个数除以总长度即可得到误码率ber
    ber_resize(resize+0.5)=bit_error_count/len_total;
    end
    % plot参数说明: 
    % 参数1是横坐标自变量,参数2是纵坐标自变量,参数3是指用说明形式描点,参数4和5代表把散点链接起来 
    resize=0.5:1:10; 
    plot(resize,ber_resize,'*',resize,ber_resize); 
    title('基于图片缩放质量的误码率图表');
    function ber_jpeg=calcute_jpeg_ber(input,output,messagefile,len_total,key)
    for compressibility=10:10:100 
    %Compressiblity是图像的质量因子,可设置在0-100范围内
    %compressibility=90;
    %读取已经隐藏信息的图像。
    fp=imread(input);
    %使用 imwrite 函数对图像进行压缩,设定压缩比例。
    imwrite(fp,output,'quality',compressibility);
    intchanged=imread(output);
    intchanged=double(intchanged);
    %p作为消息嵌入位计数器,将消息序列写回文本文件
    p=1;
    %调用随机间隔函数选取像素点
    [row,col]=randinterval(intchanged,len_total,key);
    for i=1 :len_total
        if bitand(intchanged(row(i),col(i)),1)==1
            result(p,1)=1;
        else
            result(p,1)=0;
        end
        if p ==len_total
            break;
        end
        p=p+1;
    end
    %读取原文件,即隐藏的信息,以二进制读取。并取得消息长度
    message=fopen(messagefile,'r'); 
    %按位以二进制形式读取文本内容与长度
    [msg,len_total]=fread(message,'ubit1');
    %比较取得的信息和原信息的每一位,记录不相等位数的个数。
    bit_error=find(result~=msg); %寻找不相等的位置 
    bit_error_count=size(bit_error,1); %统计不相等的个数
    %用不相等个数除以总长度即可得到误码率ber
    ber_jpeg(compressibility/10)=bit_error_count/len_total;
    end
    % plot参数说明: 
    % 参数1是横坐标自变量,参数2是纵坐标自变量,参数3是指用说明形式描点,参数4和5代表把散点链接起来 
    compressibility=10:10:100; 
    plot(compressibility,ber_jpeg,'*',compressibility,ber_jpeg); 
    title('基于图片压缩质量因子的误码率图表');

    4.计算水印相关系数PSNR——PSNR值越大,图像质量越好:

    function PSNR=calcute_psnr(input,inputchange)
    img=imread(input);  
    [h,w]=size(img);  
    %imgn=imresize(img,[floor(h/2) floor(w/2)]);  
    %imgn=imresize(imgn,[h w]); 
    imgn=imread(inputchange);
    img=double(img);  
    imgn=double(imgn);  
    %编码一个像素用多少二进制位    
    B=8;  
    %图像有多少灰度级  
    MAX=2^B-1;         
    MES=sum(sum((img-imgn).^2))/(h*w);     %均方差  
    PSNR=20*log10(MAX/sqrt(MES));           %峰值信噪比

    展开全文
  • 隐藏PHP版本信息隐藏apache版本号

    千次阅读 2018-11-29 10:02:58
    如图这两个:  修改php.ini文件: expose_php = Off 修改httpd.conf文件:(如果没有在最下面添加这两行) ServerTokens Prod ServerSignature Off 重启apache:
  • C#设置文件隐藏

    千次阅读 2018-06-15 11:54:40
    FileInfo info = new FileInfo(FilePath); if (info.Exists) { info.Attributes = FileAttributes.Hidden; }这样就设置文件为隐藏模式...
  • LSB图像信息隐藏实验(附源代码)

    万次阅读 多人点赞 2016-11-01 17:26:59
    LSB图像信息隐藏 1.掌握对图像的基本操作。 2.能够用 LSB 算法对图像进行信息隐藏 3.能够用 LSB 提取算法提取隐藏进图像的信息 4.能够反映 jpeg 压缩率与误码率之间的关系 三、【实验过程】 实验算法 1:信息隐藏 ...
  • 隐藏IIS版本信息

    千次阅读 2019-05-14 19:57:11
    漏洞现象: ... ... ...Last-Modified: Mon, 09 Nov 2015 08:...再测试版本信息已经隐藏,问题解决:curl -I -X GET http://www.xxx.com   相关参考文档: http://www.cnblogs.com/kowloon/p/9071872.html ...
  •   背景 当使用nginx做为web服务器时,在头部信息会看到版本号相关的信息,在安全扫描的时候会扫出来,要求不能显示nginx版本,避免根据已知的版本的nginx的...隐藏nginx版本信息 在nginx.conf的http里面加serv...
  • nginx 默认不隐藏版本信息,在404,502等等错误页面会显示nginx版本号,如图: 隐藏错误页nginx版本号方法: 在全局 http 下增加配置 server_tokens off; server_tokens off; # nginx 默认没有该项配置 如图...
  • 隐写术之pngIDAT隐藏信息

    千次阅读 2018-11-13 21:50:10
    ** 题目:奇怪的图片 ** 题目文件网址: ... ...说明:此题主要考察对png文件格式的了解。...https://www.cnblogs.com/k1two2/p/5170178.html pngIDAT隐藏数据 https://www.cnblogs.com/k1tw...
  • 数字图像处理 信息隐藏 LSB算法

    千次阅读 2020-04-13 16:41:11
    在对图像影响最小的位平面图像中,进行一些数值的修改,人的肉眼难以察觉,所以可以将待嵌入的图像也转化为二进制,嵌入到这些位平面当中,从而实现图片的信息隐藏。 而提取的过程则是逆向地将嵌入后的图片的对应....
  • 图像信息隐藏

    千次阅读 2015-07-17 10:17:53
     本篇介绍和讲解如何在图像中隐藏一些信息。 具体实现 基本流程  一共分为两部分:第一部分是生成隐藏的加密图像,另一部分是对加密图像解密,显示出被隐藏信息。 生成加密图像 具体代码 ? 1 2 ...
  • JavaWeb页面增加隐藏版权信息

    千次阅读 2015-07-10 14:28:19
    JavaWeb页面增加隐藏版权信息
  • 1、隐藏nginx版本信息 在nginx.conf里面加server_tokens off;就可以隐藏版本号。 2、隐藏server信息 实现方案 : 需要重新编译nginx 进入解压出来的nginx 源码 目录(不是nginx的安装目录) vi src/...
  • 一、针对如何安全有效的保护在传输过程中的信息,提出对信息的安全传输采取加密和隐藏两大保护措施,通过AES加密算法对带传输信息进行加密,然后以数字图像作为载体,利用LSB算法和DCT变换两种图像嵌入方式将所得...
  • 隐藏IIS响应头信息

    千次阅读 2018-12-28 16:01:55
    响应头信息原始头信息 Cache-Control: private Content-Length: 78457 Content-Type: text/HTML; charset=utf-8 Date: Fri, 25 Apr 2014 06:19:18 GMT Server: Microsoft-IIS/7.5 X-AspNet-Version: 4.0...
  • 1.只需要给elementui标签上边添加属性:show-overflow-tooltip="true"即可设置鼠标显示 ...2.如果鼠标移入显示内容过多的话可以设置显示的宽度或者设置隐藏的 <style> .el-tooltip__popper{ displ
  • 2、 顺序法和随机法信息隐藏位置分布     CODE lsbord.m(顺序法嵌入) function hideimg=lsbord(imgfile,info,outfile) %读取载体图像 img=imread(imgfile); %转灰度图像 if ndims(img)==3
  • 隐藏服务器header与web软件版本信息

    千次阅读 2019-01-15 10:45:24
    引入  每次当浏览器向Web服务器发起一个...而这些HTTP头是用于给Web服务器提供一些额外信息以便于处理请求。比如说吧。...还有任何在上一次传输中服务端设置的cookies也会通过Cookies HTTP头来回传到服务器,浏览...
  • 图片嵌入隐藏-大容量的信息隐藏算法

    万次阅读 热门讨论 2016-05-02 23:14:25
     这是一种基于空间域的自适应多平面位的信息隐藏算法。该算法计算复杂度低、信息隐藏量大。且有实验表明在不影响图像视觉效果的前提下,其信息隐藏量比LSB算法大,并具有更高的安全性。该算法的主要思想是对每个...
  • 整理自(来源):http://tieba.baidu.com/p/4934345324(【新手教程】利用EFI启动盘修改 隐藏bios设置)http://tieba.baidu.com/p/4905573105(#新版工具#分享一个修改insyde bios的工具——H2OEZE)(侵删) 另本文...
  • 在控制器添加如下代码即可:1、//隐藏状态栏- (BOOL)prefersStatusBarHidden{ return YES;} 2、单独修改状态栏背景颜色方法:例如:[self setStatusBarBackgroundColor:[UIColor whiteColor]];/** 设置状态栏背景...
  • 隐藏服务器头信息

    万次阅读 2017-06-20 17:53:11
    半强迫症的我,为了安全性(然并卵)和节流(就小小的一点点)考虑,需要对生产环境的服务器头信息进行隐藏,下面列出常用的修改及配置 隐藏nginx版本号 修改nginx.conf文件 在http配置项中增加 server_tokens off;...
  • 1.设置无线网络隐藏 https://jingyan.baidu.com/album/27fa7326e0f49246f8271f33.html?picindex=5 找到无线基本设置->ssid下面有一个隐藏的勾选项->勾选即可 2.查找手机或者电脑的mac地址 ...
  • tp5的设置隐藏的字段,

    千次阅读 2018-10-11 20:35:07
    //该设置只在toArray(),和subToArray()方法中起作用  protected $hidden = [];  //相关方法  public function hidden($hidden&lt;/span&gt;=[],&lt;span class="hljs-variable"&gt;$...
  • 在当前目录下创建keystore.properties文件 storePassword = 123456 keyPassword = 123456 keyAlias ...通过以上设置即可,但是注意不要把keystore.properties文件上传到git或者是SVN上面去哟
  • 用图片隐藏信息的技术实现

    千次阅读 2015-05-19 21:12:45
    如果能通过技术手段把信息隐藏在图片中,而图片本身又看不出什么异样,人工审核就看不出来。 ◇传递加密信息  最后,图片还可以用来隐藏加密的信息。关于加密的用途及重要性,俺在“ 文件加密的扫盲...
  • //隐藏地球 viewer.scene.globe.show=false;
  • Nginx 隐藏版本号和信息

    千次阅读 2018-05-02 11:24:00
    Http中的Nginx版本信息 查看http请求的response里面的header我们会发现有server这个参数,它表示服务端使用的是什么web服务器。 例如 新浪网: Server:nginx 开源中国: Server:Tengine segmentfault甚至都没有...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 463,386
精华内容 185,354
关键字:

信息隐藏设置