Loading [MathJax]/jax/output/CommonHTML/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >使用openssl加密的java解密文件

使用openssl加密的java解密文件
EN

Stack Overflow用户
提问于 2022-08-23 01:33:21
回答 1查看 302关注 0票数 -1

使用以下命令对文件进行加密:

代码语言:javascript
运行
AI代码解释
复制
openssl enc -aes-256-cbc -in file.txt -out file_enc.txt -k 1234567812345678

使用以下命令对文件进行解密:

代码语言:javascript
运行
AI代码解释
复制
openssl enc -d -aes-256-cbc -in file_enc.txt -out file.txt -k 1234567812345678

在用java打印salt和key之后,我得到:

Key=b796fbb416732ce13d39dbb60c0fb234a8f6d70e49df1c7e62e55e81d33a6bff774254ac99268856bf3afe0b95defdad

在cmd,我得到:

salt=2D7C7E1C84BD6693 key=B796FBB416732CE13D39DBB60C0FB234A8F6D70E49DF1C7E62E55E81D33A6BFF

iv =774254AC99268856BF3AFE0B95DEFDAD

跑完后:

openssl enc -aes-256 cbc -in file.txt -out file_enc.txt -pbkdf2 -k 1234567812345678 -p

我使用以下代码,但加密文件正在打印:

代码语言:javascript
运行
AI代码解释
复制
public static void main(String args[]) throws InvalidKeySpecException,
                                              NoSuchAlgorithmException,
                                              IllegalBlockSizeException,
                                              InvalidKeyException,
                                              BadPaddingException,
                                              InvalidAlgorithmParameterException,
                                              NoSuchPaddingException,
                                              IOException {
    String password = "1234567812345678";
    String algorithm = "AES/CBC/PKCS5Padding";
    IvParameterSpec ivParameterSpec = AESUtil.generateIv();
    Resource resource = new ClassPathResource("file_enc.txt");
    File inputFile = resource.getFile();
    byte[] salt = new byte[8], data = new byte[1024], tmp; 
        int keylen = 32, ivlen = 16, cnt;
        try( InputStream is = new FileInputStream(inputFile) ){
            if( is.read(salt) != 8 || !Arrays.equals(salt, "Salted__".getBytes() )
                    || is.read(salt) != 8 ) throw new Exception("salt fail");
            byte[] keyandIV = SecretKeyFactory.getInstance("PBKDF2withHmacSHA256") 
                    .generateSecret( new PBEKeySpec(password.toCharArray(), salt, 10000, (keylen+ivlen)*8) 
                    ).getEncoded();
            System.out.println("Key "+ byteArrayToHex(keyandIV));
            Cipher ciph = Cipher.getInstance("AES/CBC/PKCS5Padding"); 
            ciph.init(Cipher.DECRYPT_MODE, new SecretKeySpec(keyandIV,0,keylen,"AES"), 
                    new IvParameterSpec(keyandIV,keylen,ivlen));
            while( (cnt = is.read(data)) > 0 ){
                if( (tmp = ciph.update(data, 0, cnt)) != null ) System.out.write(tmp);
            }
            tmp = ciph.doFinal(); System.out.write(tmp);
        }
}
EN

回答 1

Stack Overflow用户

发布于 2022-08-23 04:18:13

您的getKeyFromPassword为PBKDF2创建了一个SecretkeyFactory (使用HmacSHA256),但不使用它;相反,您使用密码作为密钥,这是错误的--除非您实际上希望使用密钥(-K大写和十六进制,对于AES-256应该是64十六进制/32字节),而不是密码(-k小写和任何字符或任何长度)。(在IIRC 18下面,String.getBytes()为您提供了依赖JVM的编码,对于像真正密码这样的任意字符串,这种编码在不同的系统或环境中可能会有所不同,这将导致使用它的密码学失败,但对于示例字符串,您显示的所有实际编码都会得到相同的结果。)

但是,即使您确实使用了这个工厂,它也是不正确的,因为openssl enc默认不使用PBKDF2,它使用一个名为EVP_BytesToKey的函数,它基于但不同于PBKDF1。仅在OpenSSL 1.1.1和3.0中,您可以选择在enc中指定-pbkdf2 (和/或-iter N),如果不指定,则会给出关于“过时的密钥派生”的警告消息,您应该已经注意到了,所以我假设您要么使用过时的OpenSSL,要么试图阻止我们准确理解您的情况,从而不太可能得到有用的答案。

此外,对于任意一种密钥派生(旧的EVP_BytesToKey或可选的新PBKDF2),openssl enc默认使用salt,在加密时随机生成并写入文件;解密时必须从文件中读取salt并使用它。具体来说,跳过或丢弃前8个字节(这是固定的字符Salted__),并将接下来的8个字节作为salt,然后文件的其余部分作为密文。

取决于您想要做什么(或者您的用户/客户/其他人希望做什么),有三种可能性:

  1. 使用默认派生(与现在一样)用openssl enc -aes-256-cbc -k ...加密,并编码Java从上面的文件中读取salt,使用密码和那个salt实现EVP_BytesToKey,并将其输出用于JavaCipher中的密钥和IV (用于aes-256-cbc生成48字节,使用前32字节作为密钥,最后16字节作为IV)。EVP_BytesToKey使用的哈希默认为SHA256 1.1.0up,而MD5用于较低版本,因此您需要知道是哪个版本进行了加密才能工作,否则可以在enc命令中使用-md $hash指定哈希。在过去的十年里,已经有数百个关于这个问题的疑问;寻找EVP_BytesToKey来找到其中一些。

Cipher.对

  1. 进行加密,并将其编码为从上面的文件中读取salt,并使用您创建的密钥工厂生成48字节的“密钥”材料,您必须按照上面的方式将其分割成密钥和IV。

  1. openssl enc -aes-256-cbc -K 64hexits -iv 32hexits加密,并对openssl enc -aes-256-cbc -K 64hexits -iv 32hexits进行编码,以使用相应的二进制密钥和IV值。

命令中的

我既没有指定随机IV也没有指定PKCS5Padding

当您在openssl enc中使用旧的或新的密钥派生时,它派生IV而不是单独指定它;只有当您使用显式键(-K大写)时,才会指定-ivopenssl enc总是默认使用不同名称为pkcs5、pkcs7或pkcs5 5/7的填充,除非不需要填充( RC4或ChaCha之类的流密码或CTR、OFB、CFB等流模式)。

好吧,你好像只读了我说的一半。最根本的是,您仍然拥有没有openssl enc-pbkdf2,但是尝试用PBKDF2解密,这是完全错误的。此外,您正在读取盐,然后将其转换为十六进制,这是错误的,文件中的盐是正确的盐,您正在生成一个完全虚假的随机IV,而不是像我说的那样派生它。

具体而言,如果您(或我)使用-pbkdf2加密文件,如

代码语言:javascript
运行
AI代码解释
复制
 openssl enc -aes-cbc-256 -pbkdf2 -k 1234567812345678 

它只适用于OpenSSL 1.1.1或3.0 (即自2018年起),以下(极简式) Java代码正确地解密它:

代码语言:javascript
运行
AI代码解释
复制
static void SO73456313OpensslEnc2_Java (String[] args) throws Exception {
    // file pw: decrypt openssl(1.1.1+) enc -aes-256-cbc -pbkdf2 -k $pw
    byte[] salt = new byte[8], data = new byte[1024], tmp; 
    int keylen = 32, ivlen = 16, cnt;
    try( InputStream is = new FileInputStream(args[0]) ){
        if( is.read(salt) != 8 || !Arrays.equals(salt, "Salted__".getBytes() )
                || is.read(salt) != 8 ) throw new Exception("salt fail");
        byte[] keyandIV = SecretKeyFactory.getInstance("PBKDF2withHmacSHA256") 
                .generateSecret( new PBEKeySpec(args[1].toCharArray(), salt, 10000, (keylen+ivlen)*8) 
                ).getEncoded();
        Cipher ciph = Cipher.getInstance("AES/CBC/PKCS5Padding"); 
        ciph.init(Cipher.DECRYPT_MODE, new SecretKeySpec(keyandIV,0,keylen,"AES"), 
                new IvParameterSpec(keyandIV,keylen,ivlen));
        while( (cnt = is.read(data)) > 0 ){
            if( (tmp = ciph.update(data, 0, cnt)) != null ) System.out.write(tmp);
        }
        tmp = ciph.doFinal(); System.out.write(tmp);
    }
}

注意,在PBEKeySpec中,我使用了itercount=10000,这是enc的默认设置。您可以使用更高的数字,比如65536,这对于安全性来说可能是可取的(但这部分在这里是不讨论主题的),如果您在加密时指定了它,比如:

代码语言:javascript
运行
AI代码解释
复制
 openssl enc -aes-256-cbc -pbkdf2 -iter 65536 -k ... 

OTOH如果使用发布的命令(必须在OpenSSL 1.1.0或更低版本上),则根本无法使用PBKDF2解密。有关此情况,请参见

How to decrypt file in Java encrypted with openssl command using AES?

How to decode a string encoded with openssl aes-128-cbc using java?

Java equivalent of an OpenSSL AES CBC encryption

Java AES Decryption with keyFile using BouncyCastle SSL

CryptoJS AES encryption and Java AES decryption (加密is有时与OpenSSL兼容,包括Q中的情况)。

请记住,至少在前面的一些Qs中已经指出,您发布的命令在1.1.0up中使用了EVP_BytesToKey和SHA256,在1.0.2和更低的时候使用了MD5,所以您需要知道使用的是哪个OpenSSL或将要使用哪个OpenSSL。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73456313

复制
相关文章
api安全授权调用--OAuth协议详解!
OAuth是一个关于授权(authorization)的开放网络标准,在全世界得到广泛应用,目前的版本是2.0版。
后端技术探索
2018/08/09
8200
OAuth 详解<2> 什么是 OAuth 2.0 授权码授权类型?
demo007x/oauth2-client: Oauth2 Client package for Golang (github.com) 欢迎star
用户1418987
2023/04/11
2.1K0
OAuth 详解<2> 什么是 OAuth 2.0 授权码授权类型?
OAUTH开放授权
OAUTH开放授权为用户资源的授权提供了一个安全的、开放而又简易的标准。OAUTH的授权不会使第三方触及到用户的帐号信息例如用户名与密码等,即第三方无需使用用户的用户名与密码就可以申请获得该用户资源的授权,因此OAUTH授权是安全的,目前OAUTH的版本为2.0。
WindRunnerMax
2020/08/27
1.2K0
Oauth授权流程
我们经常会使用第三方的账号来登录某个平台,比如使用QQ账号登录爱奇艺,使用微博登录自如APP。而登录的过程中,会提示自如想访问你的微博公开资料、好友信息,或者爱奇艺要访问您QQ头像、照片等资料。那么这个过程是有一个比较复杂的授权流程,在IoT云业务测试过程中,也会有这种场景的授权流程。下面我就通过图例结合业务场景和大家介绍下oauth授权流程。
CeshirenTester
2022/06/14
3690
8种至关重要OAuth API授权流与能力
在本文中,Curity的Daniel Lindau概述了重要的OAuth授权流程和能力。
yuanyi928
2018/12/07
1.7K0
OAuth2.0授权协议
通过用户授权,第三方服务访问用户存在其他服务上的资源,而不需用户将用户名密码直接传递的资源服务器的安全控制协议。
sucl
2019/09/05
6920
OAuth2.0授权协议
[认证授权] 1.OAuth2授权
1 OAuth2解决什么问题的? 举个栗子先。小明在QQ空间积攒了多年的照片,想挑选一些照片来打印出来。然后小明在找到一家提供在线打印并且包邮的网站(我们叫它PP吧(Print Photo缩写 ?))
blackheart
2018/01/19
1.8K0
[认证授权] 1.OAuth2授权
[腾讯社区开放平台]介绍开放授权协议-OAuth
OAuth (开放授权) 是一个开放标准,允许用户授权第三方网站访问他们存储在另外的服务提供者上的信息,而不需要将用户名和密码提供给第三方网站或分享他们数据的所有内容。OAuth是OpenID的一个补充,但是完全不同的服务。 OAuth,一个让人又爱又恨的验证协议,它让许多主流的社交网站(SNS)与网络服务打开了封闭已久的验证大门,它也是在网络上公开个人或私人信息 (private data) 前最主要的验证管道之一,重要的是,在这个协议下,所有公开给外界的私有数据会受到两个阶段的保护,OAuth 保障
张善友
2018/01/19
1.8K0
[腾讯社区开放平台]介绍开放授权协议-OAuth
OAuth 2.0 授权认证详解
点击上方“芋道源码”,选择“设为星标” 管她前浪,还是后浪? 能浪的浪,才是好浪! 每天 10:33 更新文章,每天掉亿点点头发... 源码精品专栏 原创 | Java 2021 超神之路,很肝~ 中文详细注释的开源项目 RPC 框架 Dubbo 源码解析 网络应用框架 Netty 源码解析 消息中间件 RocketMQ 源码解析 数据库中间件 Sharding-JDBC 和 MyCAT 源码解析 作业调度中间件 Elastic-Job 源码解析 分布式事务中间件 TCC-Transaction
芋道源码
2022/06/20
1.9K0
OAuth 2.0 授权认证详解
[PHP] Oauth授权和本地加密
1.Oauth(开放授权)是一个开放标准,允许用户让第三方应用访问该用户在某一网站上存储的私密资源(如照片,视频,联系人列表),而无需将用户名和密码提供给第三方
唯一Chat
2019/09/10
6080
OAuth 2.0授权框架详解
在现代的网站中,我们经常会遇到使用OAuth授权的情况,比如有一个比较小众的网站,需要用户登录,但是直接让用户注册就显得非常麻烦,用户可能因为这个原因而流失,那么该网站可以使用OAuth授权,借助于github或者其他的第三方网站的认证授权,来获取相关的用户信息,从而避免了用户注册的步骤。
程序那些事
2020/11/26
1.1K0
通过管理API管理OAuth2 认证授权服务器Keycloak
我们在Keycloak Admin Console中的所有操作都有特定的Restful API,被统称为Keycloak Admin REST API。而 Keycloak Admin Client正是对Keycloak Admin REST API的Java HTTP客户端封装。我们只需要引入下面的依赖就可以集成了:
码农小胖哥
2021/09/09
2.9K0
OAuth2.0授权码模式
本文链接:https://blog.csdn.net/u014427391/article/details/97504088
SmileNicky
2019/08/29
1.1K0
OAuth2.0授权码模式
OAuth授权 | 看这篇就够了
上一篇我们介绍了单点登录(SSO),它能够实现多个系统的统一认证。今天我们来谈一谈近几年来非常流行的,大名鼎鼎的OAuth。它也能完成统一认证,而且还能做更多的事情。至于OAuth与SSO的区别,将在文章最后总结。
小忽悠
2018/09/09
1.8K0
Spring Cloud Security使用OAuth2授权服务器来保护API
首先,我们需要配置OAuth2授权服务器。在本示例中,我们将使用Spring Boot和Spring Security来配置OAuth2授权服务器。
堕落飞鸟
2023/04/13
1.1K0
OAuth 详解<4> 什么是 OAuth 2.0 隐式授权类型?
隐式授权类型是单页 JavaScript 应用程序无需中间代码交换步骤即可获取访问令牌的一种方式。它最初是为 JavaScript 应用程序(无法安全存储机密)而创建的,但仅在特定情况下才推荐使用。
用户1418987
2023/10/16
3910
OAuth 详解<4> 什么是 OAuth 2.0 隐式授权类型?
从 OAuth2 服务器获取授权授权
搭建好了基于 OWIN 的 OAuth2 服务器之后, 接下来就是如何从服务器取得授权了, 下面就介绍如何实现 OAuth2 定义的四种授权方式。
beginor
2020/08/10
1.7K0
从 OAuth2 服务器获取授权授权
OAuth系列之OAuth2.0授权码模式学习笔记
最近在学习Oauth2.0,随便记录一下从优质博客http://www.ruanyifeng.com/blog/2014/05/oauth_2_0.html 学习到的知识
SmileNicky
2022/05/07
4260
OAuth系列之OAuth2.0授权码模式学习笔记
OAuth2.0认证和授权机制
(F)资源服务器确认令牌无误,同意向客户端开放资源。 这么一个过程 2. 看到上面的流程,我们大概都有一个疑问,就是用户同意授权后这个步骤是如何授权的?怎么就算授权成功,通过什么东西去向认证服务器申请令牌?
袁新栋-jeff.yuan
2020/08/26
8890
OAuth2.0认证和授权机制
使用OAuth2实现授权服务
OAuth 2发明之初是为了解决登录认证过程中的安全性问题,使用“委托”的形式使第三方应用获得数据权限及功能。OAuth 2.0协议中,使用访问令牌ACCESS_TOKEN代替传统的账号密码,提高了互联网环境下的安全性。
关忆北.
2022/09/28
1.4K0
使用OAuth2实现授权服务

相似问题

SSRS报表通过URL以PDF格式呈现报表

011

将SSRS 2005报表以XML格式导出到PDF

11

将SSRS报表导出到Excel问题

11

使用PowerBI令牌访问AzureAD报表

122

SSRS:从主报表将钻取报表导出到Excel

13
添加站长 进交流群

领取专属 10元无门槛券

AI混元助手 在线答疑

扫码加入开发者社群
关注 腾讯云开发者公众号

洞察 腾讯核心技术

剖析业界实践案例

扫码关注腾讯云开发者公众号
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文