Encryptors 2.40__tar.gz → 2.42__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. {encryptors-2.40 → encryptors-2.42}/PKG-INFO +1 -1
  2. {encryptors-2.40 → encryptors-2.42}/setup.py +2 -2
  3. {encryptors-2.40 → encryptors-2.42}/src/Encryptors.egg-info/PKG-INFO +1 -1
  4. {encryptors-2.40 → encryptors-2.42}/src/Encryptors.egg-info/SOURCES.txt +2 -0
  5. {encryptors-2.40 → encryptors-2.42}/src/Osdental/Decorators/SecureResolver.py +1 -1
  6. {encryptors-2.40 → encryptors-2.42}/src/Osdental/Encryptor/Jwt.py +3 -3
  7. {encryptors-2.40 → encryptors-2.42}/src/Osdental/Encryptor/Rsa.py +3 -3
  8. {encryptors-2.40 → encryptors-2.42}/src/Osdental/Graphql/Extensions/AuditExtension.py +18 -13
  9. {encryptors-2.40 → encryptors-2.42}/src/Osdental/Helpers/AuditDispatcher.py +10 -1
  10. encryptors-2.42/src/Osdental/Helpers/ResponseDecryptor.py +33 -0
  11. {encryptors-2.40 → encryptors-2.42}/src/Osdental/Models/Response.py +9 -1
  12. encryptors-2.42/src/Osdental/Shared/Utils/RsaUtils.py +30 -0
  13. {encryptors-2.40 → encryptors-2.42}/README.md +0 -0
  14. {encryptors-2.40 → encryptors-2.42}/setup.cfg +0 -0
  15. {encryptors-2.40 → encryptors-2.42}/src/Encryptors.egg-info/dependency_links.txt +0 -0
  16. {encryptors-2.40 → encryptors-2.42}/src/Encryptors.egg-info/entry_points.txt +0 -0
  17. {encryptors-2.40 → encryptors-2.42}/src/Encryptors.egg-info/requires.txt +0 -0
  18. {encryptors-2.40 → encryptors-2.42}/src/Encryptors.egg-info/top_level.txt +0 -0
  19. {encryptors-2.40 → encryptors-2.42}/src/Osdental/Cli/__init__.py +0 -0
  20. {encryptors-2.40 → encryptors-2.42}/src/Osdental/Database/BaseRepository.py +0 -0
  21. {encryptors-2.40 → encryptors-2.42}/src/Osdental/Database/Connection.py +0 -0
  22. {encryptors-2.40 → encryptors-2.42}/src/Osdental/Database/__init__.py +0 -0
  23. {encryptors-2.40 → encryptors-2.42}/src/Osdental/Decorators/Grpc.py +0 -0
  24. {encryptors-2.40 → encryptors-2.42}/src/Osdental/Decorators/PublicResolver.py +0 -0
  25. {encryptors-2.40 → encryptors-2.42}/src/Osdental/Decorators/Retry.py +0 -0
  26. {encryptors-2.40 → encryptors-2.42}/src/Osdental/Decorators/SqlDataNormalizer.py +0 -0
  27. {encryptors-2.40 → encryptors-2.42}/src/Osdental/Decorators/__init__.py +0 -0
  28. {encryptors-2.40 → encryptors-2.42}/src/Osdental/Encryptor/Aes.py +0 -0
  29. {encryptors-2.40 → encryptors-2.42}/src/Osdental/Encryptor/Argon2.py +0 -0
  30. {encryptors-2.40 → encryptors-2.42}/src/Osdental/Encryptor/Bcrypt.py +0 -0
  31. {encryptors-2.40 → encryptors-2.42}/src/Osdental/Encryptor/Sha512.py +0 -0
  32. {encryptors-2.40 → encryptors-2.42}/src/Osdental/Encryptor/__init__.py +0 -0
  33. {encryptors-2.40 → encryptors-2.42}/src/Osdental/Exception/ControlledException.py +0 -0
  34. {encryptors-2.40 → encryptors-2.42}/src/Osdental/Exception/__init__.py +0 -0
  35. {encryptors-2.40 → encryptors-2.42}/src/Osdental/Graphql/Extensions/__init__.py +0 -0
  36. {encryptors-2.40 → encryptors-2.42}/src/Osdental/Graphql/Models/__init__.py +0 -0
  37. {encryptors-2.40 → encryptors-2.42}/src/Osdental/Graphql/_Exceptions/__init__.py +0 -0
  38. {encryptors-2.40 → encryptors-2.42}/src/Osdental/Graphql/_Helpers/_AuditHelper.py +0 -0
  39. {encryptors-2.40 → encryptors-2.42}/src/Osdental/Graphql/_Helpers/_ExtractAuthToken.py +0 -0
  40. {encryptors-2.40 → encryptors-2.42}/src/Osdental/Graphql/_Helpers/_TenantPolicy.py +0 -0
  41. {encryptors-2.40 → encryptors-2.42}/src/Osdental/Graphql/_Helpers/_TokenService.py +0 -0
  42. {encryptors-2.40 → encryptors-2.42}/src/Osdental/Graphql/_Helpers/__init__.py +0 -0
  43. {encryptors-2.40 → encryptors-2.42}/src/Osdental/Graphql/__init__.py +0 -0
  44. {encryptors-2.40 → encryptors-2.42}/src/Osdental/Helpers/KeyVaultService.py +0 -0
  45. {encryptors-2.40 → encryptors-2.42}/src/Osdental/Helpers/__init__.py +0 -0
  46. {encryptors-2.40 → encryptors-2.42}/src/Osdental/Http/APIClient.py +0 -0
  47. {encryptors-2.40 → encryptors-2.42}/src/Osdental/Http/_Exceptions.py +0 -0
  48. {encryptors-2.40 → encryptors-2.42}/src/Osdental/Http/__init__.py +0 -0
  49. {encryptors-2.40 → encryptors-2.42}/src/Osdental/Messaging/AzureServiceBus.py +0 -0
  50. {encryptors-2.40 → encryptors-2.42}/src/Osdental/Messaging/Kafka.py +0 -0
  51. {encryptors-2.40 → encryptors-2.42}/src/Osdental/Messaging/RabbitMQ.py +0 -0
  52. {encryptors-2.40 → encryptors-2.42}/src/Osdental/Messaging/__init__.py +0 -0
  53. {encryptors-2.40 → encryptors-2.42}/src/Osdental/Models/AuditConfig.py +0 -0
  54. {encryptors-2.40 → encryptors-2.42}/src/Osdental/Models/Token.py +0 -0
  55. {encryptors-2.40 → encryptors-2.42}/src/Osdental/Models/_Audit.py +0 -0
  56. {encryptors-2.40 → encryptors-2.42}/src/Osdental/Models/__init__.py +0 -0
  57. {encryptors-2.40 → encryptors-2.42}/src/Osdental/RedisCache/Redis.py +0 -0
  58. {encryptors-2.40 → encryptors-2.42}/src/Osdental/RedisCache/__init__.py +0 -0
  59. {encryptors-2.40 → encryptors-2.42}/src/Osdental/Rest/Context/RequestContext.py +0 -0
  60. {encryptors-2.40 → encryptors-2.42}/src/Osdental/Rest/Context/__init__.py +0 -0
  61. {encryptors-2.40 → encryptors-2.42}/src/Osdental/Rest/Middlewares/RequestContextMiddleware.py +0 -0
  62. {encryptors-2.40 → encryptors-2.42}/src/Osdental/Rest/Middlewares/__init__.py +0 -0
  63. {encryptors-2.40 → encryptors-2.42}/src/Osdental/Rest/__init__.py +0 -0
  64. {encryptors-2.40 → encryptors-2.42}/src/Osdental/Shared/Enums/Code.py +0 -0
  65. {encryptors-2.40 → encryptors-2.42}/src/Osdental/Shared/Enums/Constant.py +0 -0
  66. {encryptors-2.40 → encryptors-2.42}/src/Osdental/Shared/Enums/FileType.py +0 -0
  67. {encryptors-2.40 → encryptors-2.42}/src/Osdental/Shared/Enums/GrahpqlOperation.py +0 -0
  68. {encryptors-2.40 → encryptors-2.42}/src/Osdental/Shared/Enums/Message.py +0 -0
  69. {encryptors-2.40 → encryptors-2.42}/src/Osdental/Shared/Enums/Profile.py +0 -0
  70. {encryptors-2.40 → encryptors-2.42}/src/Osdental/Shared/Enums/__init__.py +0 -0
  71. {encryptors-2.40 → encryptors-2.42}/src/Osdental/Shared/Logger.py +0 -0
  72. {encryptors-2.40 → encryptors-2.42}/src/Osdental/Shared/Utils/CaseConverter.py +0 -0
  73. {encryptors-2.40 → encryptors-2.42}/src/Osdental/Shared/Utils/CodeGenerator.py +0 -0
  74. {encryptors-2.40 → encryptors-2.42}/src/Osdental/Shared/Utils/DataNormalizer.py +0 -0
  75. {encryptors-2.40 → encryptors-2.42}/src/Osdental/Shared/Utils/DataUtils.py +0 -0
  76. {encryptors-2.40 → encryptors-2.42}/src/Osdental/Shared/Utils/DateUtils.py +0 -0
  77. {encryptors-2.40 → encryptors-2.42}/src/Osdental/Shared/Utils/FileMetaData.py +0 -0
  78. {encryptors-2.40 → encryptors-2.42}/src/Osdental/Shared/Utils/HashValidator.py +0 -0
  79. {encryptors-2.40 → encryptors-2.42}/src/Osdental/Shared/Utils/Mapper.py +0 -0
  80. {encryptors-2.40 → encryptors-2.42}/src/Osdental/Shared/Utils/PasswordGenerator.py +0 -0
  81. {encryptors-2.40 → encryptors-2.42}/src/Osdental/Shared/Utils/QueryGenerator.py +0 -0
  82. {encryptors-2.40 → encryptors-2.42}/src/Osdental/Shared/Utils/TextProcessor.py +0 -0
  83. {encryptors-2.40 → encryptors-2.42}/src/Osdental/Shared/Utils/__init__.py +0 -0
  84. {encryptors-2.40 → encryptors-2.42}/src/Osdental/Shared/__init__.py +0 -0
  85. {encryptors-2.40 → encryptors-2.42}/src/Osdental/Storage/AzureBlobStorage.py +0 -0
  86. {encryptors-2.40 → encryptors-2.42}/src/Osdental/Storage/S3Storage.py +0 -0
  87. {encryptors-2.40 → encryptors-2.42}/src/Osdental/Storage/__init__.py +0 -0
  88. {encryptors-2.40 → encryptors-2.42}/src/Osdental/__init__.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: Encryptors
3
- Version: 2.40
3
+ Version: 2.42
4
4
  Summary: End-to-end algorithm library
5
5
  Author: OSDental LLC
6
6
  Author-email: support@osdental.ai
@@ -1,8 +1,8 @@
1
1
  from setuptools import setup, find_packages
2
-
2
+ # ANDERSON ESTO YA SE SUBIO Y ESTA ESTABLE, AUN TE QUEDA PENDIENTE LA AUDITORIA CON RSA Y AES DE ACCESSTOKEN
3
3
  setup(
4
4
  name="Encryptors",
5
- version="2.40",
5
+ version="2.42",
6
6
  author="OSDental LLC",
7
7
  author_email="support@osdental.ai",
8
8
  description="End-to-end algorithm library",
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: Encryptors
3
- Version: 2.40
3
+ Version: 2.42
4
4
  Summary: End-to-end algorithm library
5
5
  Author: OSDental LLC
6
6
  Author-email: support@osdental.ai
@@ -38,6 +38,7 @@ src/Osdental/Graphql/_Helpers/_TokenService.py
38
38
  src/Osdental/Graphql/_Helpers/__init__.py
39
39
  src/Osdental/Helpers/AuditDispatcher.py
40
40
  src/Osdental/Helpers/KeyVaultService.py
41
+ src/Osdental/Helpers/ResponseDecryptor.py
41
42
  src/Osdental/Helpers/__init__.py
42
43
  src/Osdental/Http/APIClient.py
43
44
  src/Osdental/Http/_Exceptions.py
@@ -77,6 +78,7 @@ src/Osdental/Shared/Utils/HashValidator.py
77
78
  src/Osdental/Shared/Utils/Mapper.py
78
79
  src/Osdental/Shared/Utils/PasswordGenerator.py
79
80
  src/Osdental/Shared/Utils/QueryGenerator.py
81
+ src/Osdental/Shared/Utils/RsaUtils.py
80
82
  src/Osdental/Shared/Utils/TextProcessor.py
81
83
  src/Osdental/Shared/Utils/__init__.py
82
84
  src/Osdental/Storage/AzureBlobStorage.py
@@ -37,7 +37,7 @@ def secure_resolver(action = None):
37
37
 
38
38
  context.audit_plain_response = copy.deepcopy(result)
39
39
 
40
- if result.data is not None:
40
+ if result.data is not None and result.encryption_type == "AES" and result.key is None:
41
41
  result.data = AES.encrypt(aes_auth, result.data)
42
42
 
43
43
  return result.send()
@@ -1,5 +1,5 @@
1
1
  import jwt
2
- from typing import Dict
2
+ from typing import Dict, Any
3
3
  from cryptography.hazmat.primitives import serialization
4
4
  from cryptography.hazmat.backends import default_backend
5
5
  from Osdental.Exception.ControlledException import JWTokenException
@@ -11,7 +11,7 @@ class JWT:
11
11
 
12
12
  @staticmethod
13
13
  def generate_token(
14
- payload: Dict[str, str], jwt_secret_key: str, algorithm="HS256"
14
+ payload: Dict[str, Any], jwt_secret_key: str, algorithm="HS256"
15
15
  ) -> str:
16
16
  try:
17
17
  token = jwt.encode(payload, jwt_secret_key, algorithm=algorithm)
@@ -22,7 +22,7 @@ class JWT:
22
22
  raise JWTokenException(message=Message.UNEXPECTED_ERROR_MSG, error=str(e))
23
23
 
24
24
  @staticmethod
25
- def extract_payload(jwt_token: str, jwt_secret_key: str) -> Dict[str, str]:
25
+ def extract_payload(jwt_token: str, jwt_secret_key: str) -> Dict[str, Any]:
26
26
  try:
27
27
  payload = jwt.decode(jwt_token, jwt_secret_key, algorithms=["HS256"])
28
28
  return payload
@@ -1,6 +1,6 @@
1
1
  import json
2
2
  from base64 import b64decode, b64encode
3
- from typing import Dict
3
+ from typing import Dict, Any
4
4
  from cryptography.hazmat.primitives import serialization
5
5
  from cryptography.hazmat.primitives.asymmetric import padding
6
6
  from cryptography.hazmat.primitives import hashes
@@ -12,7 +12,7 @@ from Osdental.Shared.Enums.Constant import Constant
12
12
  class RSAEncryptor:
13
13
 
14
14
  @staticmethod
15
- def encrypt(data:str | Dict[str,str], public_key_rsa:str) -> str:
15
+ def encrypt(data: str | Dict[str, Any], public_key_rsa: str) -> str:
16
16
  try:
17
17
  if isinstance(data, dict):
18
18
  data = json.dumps(data)
@@ -36,7 +36,7 @@ class RSAEncryptor:
36
36
 
37
37
 
38
38
  @staticmethod
39
- def decrypt(data:str, private_key_rsa:str, silent:bool = False) -> str:
39
+ def decrypt(data: str, private_key_rsa: str, silent: bool = False) -> str:
40
40
  try:
41
41
  encrypted_bytes = b64decode(data)
42
42
  private_key = serialization.load_pem_private_key(private_key_rsa.encode(Constant.DEFAULT_ENCODING), password=None)
@@ -1,4 +1,5 @@
1
1
  import json
2
+ import copy
2
3
  from graphql.pyutils import is_awaitable
3
4
  from ariadne.types import Extension
4
5
  from Osdental.Shared.Logger import logger
@@ -9,6 +10,7 @@ from Osdental.Rest.Context.RequestContext import (
9
10
  RequestContext
10
11
  )
11
12
  from Osdental.Graphql.Models import BaseGraphQLContext
13
+ from Osdental.Helpers.ResponseDecryptor import encryptor_data, VALID_TYPES
12
14
  from Osdental.Shared.Enums.Constant import Constant
13
15
 
14
16
  class AuditExtension(Extension):
@@ -29,37 +31,36 @@ class AuditExtension(Extension):
29
31
 
30
32
  def _should_skip(self, body) -> bool:
31
33
  query = body.get("query", "") or ""
32
- return "__schema" in query or "__type" in query
34
+ return "__schema" in query or "__type(" in query
33
35
 
34
36
  async def resolve(self, next_, root, info, **kwargs):
35
37
 
36
38
  context: BaseGraphQLContext = info.context
37
39
  request = context.request
38
40
 
39
- # 🔹 cache body
41
+ # cache body
40
42
  if not hasattr(context, "_cached_body"):
41
43
  context._cached_body = await request.json()
42
44
 
43
45
  body = context._cached_body
44
46
 
45
- # 🔹 skip introspection
47
+ # skip introspection
46
48
  if self._should_skip(body):
47
49
  result = next_(root, info, **kwargs)
48
50
  if is_awaitable(result):
49
51
  result = await result
50
52
  return result
51
53
 
52
- # 🔥 CLAVE
53
54
  is_root = root is None
54
55
 
55
- # 🔥 SOLO ROOT → TODO TU SISTEMA
56
+ # SOLO ROOT
56
57
  if is_root:
57
58
 
58
- # 🔹 identificar resolver público
59
+ # identificar resolver público
59
60
  resolver_fn = getattr(next_, "__wrapped__", next_)
60
61
  is_public = getattr(resolver_fn, "_is_public", False)
61
62
 
62
- # 🔹 inicializar auth UNA SOLA VEZ
63
+ # inicializar auth UNA SOLA VEZ
63
64
  if not hasattr(context, "_auth_initialized"):
64
65
  context._auth_initialized = True
65
66
 
@@ -85,13 +86,13 @@ class AuditExtension(Extension):
85
86
  context.token = original_token
86
87
  context.aes_auth = aes_auth
87
88
 
88
- # 🔐 VALIDACIÓN SOLO ROOT
89
+ # VALIDACIÓN SOLO ROOT
89
90
  original_token = getattr(context, "_original_token", None)
90
91
 
91
92
  if not is_public and not original_token:
92
93
  raise ValueError("Authorization required")
93
94
 
94
- # 🔹 payload
95
+ # payload
95
96
  variables = body.get("variables") or {}
96
97
 
97
98
  encrypted_payload = (
@@ -131,7 +132,7 @@ class AuditExtension(Extension):
131
132
  )
132
133
  context.token = token
133
134
 
134
- # 🔹 auditoría request
135
+ # auditoría request payload
135
136
  if not self.request_payload:
136
137
  token = context.token
137
138
 
@@ -144,18 +145,22 @@ class AuditExtension(Extension):
144
145
  "user": token.user_full_name if token else "Public"
145
146
  }
146
147
 
147
- # 🔥 SIEMPRE ejecutar resolver (root + fields)
148
+ # SIEMPRE ejecutar resolver (root + fields)
148
149
  result = next_(root, info, **kwargs)
149
150
 
150
151
  if is_awaitable(result):
151
152
  result = await result
152
153
 
153
- # 🔹 SOLO ROOT captura resultado final
154
+ # SOLO ROOT captura resultado final
154
155
  if is_root and self.result is None:
155
156
  self.result = result
156
157
 
157
158
  if not getattr(context, "audit_plain_response", None):
158
- context.audit_plain_response = result
159
+ if result.encryption_type in VALID_TYPES and result.key:
160
+ result_copy = copy.deepcopy(result)
161
+ result = encryptor_data(result.encryption_type, result.key, result.data)
162
+
163
+ context.audit_plain_response = result_copy
159
164
 
160
165
  return result
161
166
 
@@ -4,6 +4,7 @@ from fastapi import Request
4
4
  from Osdental.Models.AuditConfig import AuditConfig
5
5
  from Osdental.Messaging import IMessageQueue
6
6
  from Osdental.Graphql._Helpers._AuditHelper import AuditHelper
7
+ from Osdental.Helpers.ResponseDecryptor import decryptor_data, VALID_TYPES
7
8
  from Osdental.Models._Audit import Audit
8
9
  from Osdental.Models.Response import Response
9
10
  from Osdental.Shared.Enums.Constant import Constant
@@ -74,7 +75,7 @@ class AuditDispatcher:
74
75
  async def _process(self, payload: Dict[str, Any]):
75
76
  request = payload["request"]
76
77
  request_payload = payload["request_payload"]
77
- result = payload["result"]
78
+ result: Response = payload["result"]
78
79
  audit_type = payload["audit_type"]
79
80
 
80
81
  operation_name = request_payload.get("operation_name")
@@ -96,6 +97,11 @@ class AuditDispatcher:
96
97
  message = result.message
97
98
  data = result.data
98
99
  error = result.error if result.error else message
100
+
101
+ # Obtencion de campos adicionales cuando es otro tipo de encriptacion o clave
102
+ encryption_type = result.encryption_type
103
+ key = result.key
104
+
99
105
 
100
106
  if audit_type == Constant.MESSAGE_LOG_INTERNAL:
101
107
 
@@ -121,6 +127,9 @@ class AuditDispatcher:
121
127
  audit_message = request_audit_payload | payload
122
128
 
123
129
  else:
130
+ if encryption_type in VALID_TYPES and key:
131
+ data = decryptor_data(encryption_type, key, data)
132
+
124
133
  payload = AuditHelper.build_final_payload(
125
134
  _type="RESPONSE",
126
135
  status_code=status_code,
@@ -0,0 +1,33 @@
1
+ from typing import Dict, Any
2
+ from Osdental.Encryptor.Aes import AES
3
+ from Osdental.Encryptor.Rsa import RSAEncryptor
4
+ from Osdental.Shared.Logger import logger
5
+
6
+ VALID_TYPES = {"RSA", "AES"}
7
+
8
+ def encryptor_data(encryption_type: str, key: str, data: Dict[str, Any] | str) -> Any:
9
+ match encryption_type:
10
+
11
+ case "AES":
12
+ return AES.encrypt(key, data)
13
+
14
+ case "RSA":
15
+ return RSAEncryptor.encrypt(data, key)
16
+
17
+ case _:
18
+ logger.warning(f"Encryption type '{encryption_type}' not supported.")
19
+ return data
20
+
21
+ def decryptor_data(encryption_type: str, key: str, data: Dict[str, Any] | str) -> Any:
22
+
23
+ match encryption_type:
24
+
25
+ case "AES":
26
+ return AES.decrypt(key, data)
27
+
28
+ case "RSA":
29
+ return RSAEncryptor.decrypt(data, key)
30
+
31
+ case _:
32
+ logger.warning(f"Encryption type '{encryption_type}' not supported.")
33
+ return data
@@ -1,5 +1,5 @@
1
1
  from dataclasses import dataclass, field, asdict
2
- from typing import Optional, Any
2
+ from typing import Optional, Any, Literal
3
3
  from Osdental.Shared.Enums.Code import Code
4
4
  from Osdental.Shared.Enums.Message import Message
5
5
 
@@ -9,6 +9,8 @@ class Response:
9
9
  message: str = field(default=Message.PROCESS_SUCCESS_MSG)
10
10
  data: Optional[Any] = None
11
11
  error: Optional[str] = None
12
+ encryption_type: Literal["AES", "RSA", "NORMAL"] = "AES"
13
+ key: Optional[str] = None
12
14
 
13
15
  def send(self):
14
16
  response = asdict(self)
@@ -16,4 +18,10 @@ class Response:
16
18
  if response["error"] is None:
17
19
  response.pop("error")
18
20
 
21
+ if response["encryption_type"]:
22
+ response.pop("encryption_type")
23
+
24
+ if response["key"]:
25
+ response.pop("key")
26
+
19
27
  return response
@@ -0,0 +1,30 @@
1
+
2
+ def normalize_rsa_keys(key_str: str, is_private: bool = True) -> str:
3
+ """
4
+ Normaliza una llave RSA (privada o pública) para que sea compatible con cryptography.
5
+ Si is_private=True, normaliza la llave privada; si False, normaliza la llave pública.
6
+ """
7
+
8
+ # Determinar encabezados correctos
9
+ if is_private:
10
+ header = "-----BEGIN RSA PRIVATE KEY-----"
11
+ footer = "-----END RSA PRIVATE KEY-----"
12
+ invalid_texts = ["-----BEGINRSAPRIVATEKEY-----", "-----ENDRSAPRIVATEKEY-----",
13
+ "-----BEGIN RSA PRIVATE KEY-----", "-----END RSA PRIVATE KEY-----"]
14
+ else:
15
+ header = "-----BEGIN PUBLIC KEY-----"
16
+ footer = "-----END PUBLIC KEY-----"
17
+ invalid_texts = ["-----BEGINPUBLICKEY-----", "-----ENDPUBLICKEY-----",
18
+ "-----BEGIN PUBLIC KEY-----", "-----END PUBLIC KEY-----"]
19
+
20
+ # Limpiar encabezados inválidos y espacios
21
+ for text in invalid_texts:
22
+ key_str = key_str.replace(text, "")
23
+ key_str = key_str.replace("\r", "").replace(" ", "").replace("\n", "")
24
+
25
+ # Dividir en líneas de 64 caracteres
26
+ lines = [key_str[i:i+64] for i in range(0, len(key_str), 64)]
27
+
28
+ # Reconstruir PEM válido
29
+ pem = f"{header}\n" + "\n".join(lines) + f"\n{footer}\n"
30
+ return pem
File without changes
File without changes