软件设计师-上午题-09 设计模式(4分)

设计模式分值一般在上午题中为4分,下午题为试题五(C++)、试题六(Java)。

目录

1 设计模式要素

1.1 真题

2 创建型设计模式

2.1 简单工厂模式

2.2 工厂方法模式

2.3 抽象工厂模式

2.3.1 真题

2.4 生成器模式

2.4.1 真题

2.5 原型模式

2.6 单例模式

2.6.1 真题

3 结构型设计模式

3.1 适配器模式

3.1.1 真题

3.2 桥接模式

3.2.1 真题

3.3 组合模式

3.3.1 真题

3.4 装饰器模式

3.4.1 真题

3.5 外观模式

3.5.1 真题

3.6 享元模式

3.6.1 真题

3.7 代理模式

3.7.1 真题

4 行为型设计模式

4.1 责任链模式

4.2 命令模式

4.2.1 真题

4.3 解释器模式

4.4 迭代器模式

4.5 中介者模式

4.5.1 真题

4.6 备忘录模式

4.7 观察者模式

4.7.1 真题

4.8 状态模式

4.8.1 真题

4.9 策略模式

4.9.1 真题

4.10 模板方法模式

4.11 访问者模式

4.11.1 真题

5 设计模式总和


1 设计模式要素

1.1 真题

1.2014年下半年第41、42题

2 创建型设计模式

2.1 简单工厂模式

2.2 工厂方法模式

2.3 抽象工厂模式

2.3.1 真题

1.2010年上半年第43、44题

2.2016年上半年第44题

2.4 生成器模式

2.4.1 真题

1.2014年下半年第46、47题

2.2016年下半年第46、47题

3.2020年下半年第44、45、46、47题

2.5 原型模式

2.6 单例模式

2.6.1 真题

1.2011年上半年第46题

2.2012年下半年第47题

3.2015年下半年第44题

3 结构型设计模式

3.1 适配器模式

3.1.1 真题

1.2011年上半年第47题

3.2 桥接模式

3.2.1 真题

1.2011年上半年第44、45题

2.2018年上半年第44、45、46、47题

3.2019年下半年第44、45、46、47题

3.3 组合模式

3.3.1 真题

1.2012年上半年第45、46、47题

2.2013年下半年第46、47题

3.2015年上半年第44、45、46题

3.4 装饰器模式

3.4.1 真题

1.2011年下半年第43题

3.5 外观模式

3.5.1 真题

1.2014年上半年第44、45题

2.2017年上半年第46、47题

3.6 享元模式

3.6.1 真题

1.2016年上半年第47题

3.7 代理模式

3.7.1 真题

1.2011年下半年第44题

4 行为型设计模式

4.1 责任链模式

4.2 命令模式

4.2.1 真题

1.2016年上半年第45题

2.2021年上半年第44、45、46题

4.3 解释器模式

4.4 迭代器模式

4.5 中介者模式

4.5.1 真题

1.2021年下半年第44、45、46题

4.6 备忘录模式

4.7 观察者模式

4.7.1 真题

1.2009年下半年第46、47题

2.2010年下半年第46、47题

3.2011年下半年第40、41题

4.2013年下半年第45题

5.2016年上半年第46题

6.2017年上半年第44、45题

7.2019年上半年第47题

4.8 状态模式

4.8.1 真题

1.2012年下半年第44、45、46题

2.2017年下半年第44、45、46、47题

4.9 策略模式

4.9.1 真题

1.2013年下半年第44题

2.2016年下半年第44、45题

3.2021年下半年第47题

4.10 模板方法模式

4.11 访问者模式

4.11.1 真题

1.2015年上半年第47题

2.2018年上半年第44、45、46、47题

5 设计模式总和

1.2009年上半年第43、44、45题

2.2009年下半年第43、44、45题

3.2012年上半年第44题

4.2013年上半年第44、45、46、47题

5.2014年上半年第46、47题

6.2014年下半年第43、44题

7.2015年上半年第45、46、47题

8.2019年上半年第44、45、46题

修改加密函数以支持二进制数据%%AES实现 =================================================== function [encrypted, iv_salt] = AES_Encrypt(plaintext, key) % 生成动态salt和iv,各16字节 salt = randi([0 255], 1, 16, 'uint8'); iv = randi([0 255], 1, 16, 'uint8'); iv_salt = [salt iv]; % 合并salt和iv输出(32字节) key = AES_KeyDerivation(key, 16, salt); % 传入动态salt cipher = javax.crypto.Cipher.getInstance('AES/CBC/PKCS5Padding'); cipher.init(javax.crypto.Cipher.ENCRYPT_MODE, ... javax.crypto.spec.SecretKeySpec(key, 'AES'), ... javax.crypto.spec.IvParameterSpec(iv)); % 使用原始iv encrypted = cipher.doFinal(unicode2native(plaintext, 'UTF-8')); encrypted = typecast(encrypted, 'uint8'); encrypted = encrypted(:).'; end function decrypted = AES_Decrypt(ciphertext, key, iv_salt) try % 从合并参数离salt和iv if length(iv_salt) ~= 32 error('IV/Salt参数长度错误,应为32字节'); end salt = iv_salt(1:16); iv = iv_salt(17:32); % 确保类型正确 salt = uint8(salt); iv = uint8(iv); ciphertext = uint8(ciphertext); % 密钥派生 key = AES_KeyDerivation(key, 16, salt); % 创建Java对象 cipher = javax.crypto.Cipher.getInstance('AES/CBC/PKCS5Padding'); keySpec = javax.crypto.spec.SecretKeySpec(key, 'AES'); ivSpec = javax.crypto.spec.IvParameterSpec(iv); % 初始化解密模式 cipher.init(javax.crypto.Cipher.DECRYPT_MODE, keySpec, ivSpec); % 执行解密 decryptedBytes = cipher.doFinal(ciphertext); decryptedBytes = typecast(decryptedBytes, 'uint8'); % 转换为字符串 decrypted = native2unicode(decryptedBytes, 'UTF-8'); catch ME if contains(ME.message, 'InvalidKeyException') errordlg('密钥错误,请检查加密密钥!','解密失败'); else rethrow(ME); end end end function derivedKey = AES_KeyDerivation(password, keyLength, salt) iterations = 1000000; % 将密码转换为Java char[] passwordChars = java.lang.String(password).toCharArray(); % 将salt转为Java byte[](MATLAB uint8转Java有符号byte) saltBytes = typecast(salt, 'int8'); % 构造密钥规范 spec = javax.crypto.spec.PBEKeySpec(... passwordChars, ... saltBytes, ... iterations, ... keyLength*8); % 生成密钥 factory = javax.crypto.SecretKeyFactory.getInstance('PBKDF2WithHmacSHA256'); tmpKey = factory.generateSecret(spec); derivedKey = typecast(tmpKey.getEncoded(), 'uint8'); end
最新发布
03-16
<think>好的,我需要帮助用户修改现有的AES加密函数以支持二进制数据。首先,我得仔细阅读用户提供的代码,理解当前实现的功能和潜在问。 用户当前的加密函数AES_Encrypt和解密函数AES_Decrypt似乎主要用于处理文本数据,因为加密部使用了unicode2native将字符串转换为UTF-8字节,而解密部用native2unicode将字节转回字符串。但用户的需求是处理二进制数据,比如图片或文件,所以这些转换步骤可能不合适,会导致二进制数据被错误处理。 接下来,我需要找出代码中处理数据输入输出的地方。加密函数中的plaintext参数应该是文本,但为了支持二进制,应该允许输入是uint8类型的数组。同样,解密后的输出不应转换为字符串,而是保持uint8数组。 在加密函数中,unicode2native(plaintext, 'UTF-8')这一行会将字符串转为字节,但如果plaintext已经是二进制数据,这一步会出错。应该检查输入类型,如果是字符,则转换;否则直接使用。或者强制用户传入uint8数据,但可能破坏原有功能。可能需要修改函数,移除unicode2native,直接接受uint8输入,并在文档中说明。 解密函数中的native2unicode(decryptedBytes, 'UTF-8')同样存在问,解密后的数据可能是二进制而非文本,所以应直接返回uint8数组,而不是字符串。这里需要删除这个转换步骤,让decrypted直接是uint8数组。 另外,需要确保加密和解密过程中数据类型的统一。例如,加密后的encrypted已经是uint8数组,而解密时ciphertext需要是uint8,这可能没问,但需要验证Java加密解密接口是否接受uint8数组输入。可能需要将uint8转换为int8,因为Java的byte是有符号的,但MATLAB的typecast函数处理应该正确。 密钥派生函数中的salt处理,当前salt是uint8,转换为int8可能有问,但MATLAB的typecast函数会将二进制数据直接转换,可能没问。不过需要确保PBKDF2过程中salt的正确使用。 还需要测试修改后的函数是否能正确处理二进制数据。例如,生成随机uint8数组作为plaintext,加密后再解密,确认结果一致。同时检查原有文本加密是否仍能工作,或者是否需要调整输入方式。 总结修改步骤: 1. 加密函数中移除unicode2native,直接处理uint8输入。 2. 解密函数中移除native2unicode,返回uint8数组。 3. 更新函数文档,说明支持二进制数据,输入需为uint8。 4. 处理可能的类型转换问,确保与Java的兼容性。 5. 添加错误处理,比如输入不是uint8时的提示。 6. 测试修改后的函数是否兼容文本和二进制数据,或者开函数处理不同情况。 可能遇到的问:如果用户仍想加密文本,需要确保他们先将字符串转换为UTF-8字节。或者保留原有逻辑,通过参数选择处理模式。但用户明确要求支持二进制,所以可能直接修改为处理uint8输入更合适,同时要求文本数据在调用前转换为字节。 最后,更新函数代码,调整输入输出处理部,并进行测试验证。</think>以下是针对AES加密函数支持二进制数据的修改指南,步骤说明: --- ### **一、现有代码问析** 1. **输入输出类型限制** - 加密函数`unicode2native`强制将字符串转为UTF-8字节,但二进制数据(如图片/文件)应为`uint8`数组 - 解密函数`native2unicode`将字节转为字符串,会破坏二进制数据的完整性 2. **数据类型兼容性** - Java加密接口要求输入为`int8`(有符号字节),而MATLAB默认使用`uint8`(无符号),需正确处理类型转换 --- ### **二、具体修改步骤** #### **加密函数修改** ```matlab function [encrypted, iv_salt] = AES_Encrypt(plaintext, key) % 生成动态salt和iv,各16字节 salt = randi([0 255], 1, 16, 'uint8'); iv = randi([0 255], 1, 16, 'uint8'); iv_salt = [salt iv]; % 合并salt和iv输出(32字节) key = AES_KeyDerivation(key, 16, salt); cipher = javax.crypto.Cipher.getInstance('AES/CBC/PKCS5Padding'); cipher.init(javax.crypto.Cipher.ENCRYPT_MODE, ... javax.crypto.spec.SecretKeySpec(key, 'AES'), ... javax.crypto.spec.IvParameterSpec(iv)); % 修改点:直接处理uint8输入,移除unicode转换 if ischar(plaintext) plaintext = unicode2native(plaintext, 'UTF-8'); % 兼容旧版文本输入 end encrypted = cipher.doFinal(typecast(plaintext, 'int8')); % 转为Java兼容的int8 encrypted = typecast(encrypted, 'uint8'); % 转回MATLAB的uint8 encrypted = encrypted(:).'; end ``` #### **解密函数修改** ```matlab function decrypted = AES_Decrypt(ciphertext, key, iv_salt) try if length(iv_salt) ~= 32 error('IV/Salt参数长度错误,应为32字节'); end salt = uint8(iv_salt(1:16)); iv = uint8(iv_salt(17:32)); key = AES_KeyDerivation(key, 16, salt); cipher = javax.crypto.Cipher.getInstance('AES/CBC/PKCS5Padding'); cipher.init(javax.crypto.Cipher.DECRYPT_MODE, ... javax.crypto.spec.SecretKeySpec(key, 'AES'), ... javax.crypto.spec.IvParameterSpec(iv)); % 修改点:直接返回uint8,移除字符串转换 decrypted = cipher.doFinal(typecast(ciphertext, 'int8')); % 转为Java的int8 decrypted = typecast(decrypted, 'uint8'); % 转回MATLAB的uint8 catch ME if contains(ME.message, 'InvalidKeyException') error('解密失败: 密钥错误'); else rethrow(ME); end end end ``` #### **密钥派生函数微调** ```matlab function derivedKey = AES_KeyDerivation(password, keyLength, salt) iterations = 1000000; passwordChars = java.lang.String(password).toCharArray(); % 确保salt类型正确(MATLAB uint8 → Java byte[]) saltBytes = typecast(salt, 'int8'); spec = javax.crypto.spec.PBEKeySpec(... passwordChars, saltBytes, iterations, keyLength*8); factory = javax.crypto.SecretKeyFactory.getInstance('PBKDF2WithHmacSHA256'); tmpKey = factory.generateSecret(spec); derivedKey = typecast(tmpKey.getEncoded(), 'uint8'); end ``` --- ### **三、关键修改说明** 1. **数据类型统一** - 加密输入:接受`uint8`数组,兼容文本(自动转UTF-8)和二进制数据 - 解密输出:直接返回`uint8`数组,避免字符串转换破坏数据 2. **Java兼容性处理** - 使用`typecast(..., 'int8')`将MATLAB的`uint8`转为Java有符号byte - 加密结果通过`typecast(..., 'uint8')`转回MATLAB标准格式 3. **错误处理优化** - 解密时明确检查`InvalidKeyException`,提升错误信息可读性 --- ### **四、使用示例** ```matlab % 加密二进制数据(如图片) imgData = imread('test.png'); binData = uint8(imgData(:)); % 转为uint8流 [encrypted, iv_salt] = AES_Encrypt(binData, 'myPassword'); % 解密恢复数据 decrypted = AES_Decrypt(encrypted, 'myPassword', iv_salt); recoveredImg = reshape(decrypted, size(imgData)); % 还原为图像矩阵 ``` --- ### **五、注意事项** - **输入规范**:明文/密文必须为`uint8`数组,文本需先转UTF-8: `unicode2native('你好', 'UTF-8')` - **性能优化**:大文件建议块处理,避免内存溢出 - **模式选择**:CBC模式需确保IV唯一性,当前代码已通过随机生成IV满足要求
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值